Skip to content

Commit a5350f0

Browse files
committed
Use modern python type hints.
Replace Dict, List, Tuple with dict, list, tuple. Replace Optional[str] with str | None.
1 parent 90eb1d8 commit a5350f0

18 files changed

Lines changed: 144 additions & 142 deletions

AGENTS.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@
3232
- Indentation: 4 spaces. Line length: 140 (see `pyproject.toml`).
3333
- Naming: modules/functions/variables `snake_case`; classes `CamelCase`; tests `test_*.py`.
3434
- Keep imports sorted and unused code removed (ruff enforces).
35+
- Use lowercase type hints for dict, list, tuples etc.
36+
- Use | for Unions and | None for Optional.
3537

3638
## Testing Guidelines
3739
- Framework: Pytest with coverage (`coverage run -m pytest` via tox).

litecli/clistyle.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from __future__ import annotations
22

33
import logging
4-
from typing import Dict, List, Tuple
4+
55

66
import pygments.styles
77
from pygments.token import string_to_tokentype, Token
@@ -14,7 +14,7 @@
1414
logger = logging.getLogger(__name__)
1515

1616
# map Pygments tokens (ptk 1.0) to class names (ptk 2.0).
17-
TOKEN_TO_PROMPT_STYLE: Dict[Token, str] = {
17+
TOKEN_TO_PROMPT_STYLE: dict[Token, str] = {
1818
Token.Menu.Completions.Completion.Current: "completion-menu.completion.current",
1919
Token.Menu.Completions.Completion: "completion-menu.completion",
2020
Token.Menu.Completions.Meta.Current: "completion-menu.meta.completion.current",
@@ -43,10 +43,10 @@
4343
}
4444

4545
# reverse dict for cli_helpers, because they still expect Pygments tokens.
46-
PROMPT_STYLE_TO_TOKEN: Dict[str, Token] = {v: k for k, v in TOKEN_TO_PROMPT_STYLE.items()}
46+
PROMPT_STYLE_TO_TOKEN: dict[str, Token] = {v: k for k, v in TOKEN_TO_PROMPT_STYLE.items()}
4747

4848

49-
def parse_pygments_style(token_name: str, style_object, style_dict: Dict[str, str]) -> Tuple[Token, str]:
49+
def parse_pygments_style(token_name: str, style_object, style_dict: dict[str, str]) -> tuple[Token, str]:
5050
"""Parse token type and style string.
5151
5252
:param token_name: str name of Pygments token. Example: "Token.String"
@@ -62,13 +62,13 @@ def parse_pygments_style(token_name: str, style_object, style_dict: Dict[str, st
6262
return token_type, style_dict[token_name]
6363

6464

65-
def style_factory(name: str, cli_style: Dict[str, str]) -> _MergedStyle:
65+
def style_factory(name: str, cli_style: dict[str, str]) -> _MergedStyle:
6666
try:
6767
style = pygments.styles.get_style_by_name(name)
6868
except ClassNotFound:
6969
style = pygments.styles.get_style_by_name("native")
7070

71-
prompt_styles: List[Tuple[str, str]] = []
71+
prompt_styles: list[tuple[str, str]] = []
7272
# prompt-toolkit used pygments tokens for styling before, switched to style
7373
# names in 2.0. Convert old token types to new style names, for backwards compatibility.
7474
for token in cli_style:
@@ -90,7 +90,7 @@ def style_factory(name: str, cli_style: Dict[str, str]) -> _MergedStyle:
9090
return merge_styles([style_from_pygments_cls(style), override_style, Style(prompt_styles)])
9191

9292

93-
def style_factory_output(name: str, cli_style: Dict[str, str]):
93+
def style_factory_output(name: str, cli_style: dict[str, str]):
9494
try:
9595
style = pygments.styles.get_style_by_name(name).styles
9696
except ClassNotFound:

litecli/clitoolbar.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
from __future__ import annotations
22

3-
from typing import Callable, List, Tuple
3+
from typing import Callable
44

55
from prompt_toolkit.key_binding.vi_state import InputMode
66
from prompt_toolkit.enums import EditingMode
77
from prompt_toolkit.application import get_app
88

99

10-
def create_toolbar_tokens_func(cli, show_fish_help: Callable[[], bool]) -> Callable[[], List[Tuple[str, str]]]:
10+
def create_toolbar_tokens_func(cli, show_fish_help: Callable[[], bool]) -> Callable[[], list[tuple[str, str]]]:
1111
"""Return a function that generates the toolbar tokens."""
1212

13-
def get_toolbar_tokens() -> List[Tuple[str, str]]:
14-
result: List[Tuple[str, str]] = []
13+
def get_toolbar_tokens() -> list[tuple[str, str]]:
14+
result: list[tuple[str, str]] = []
1515
result.append(("class:bottom-toolbar", " "))
1616

1717
if cli.multi_line:

litecli/completion_refresher.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from __future__ import annotations
22

33
import threading
4-
from typing import Callable, Dict, List, Optional, Tuple
4+
from typing import Callable
55

66
from .packages.special.main import COMMANDS
77
from collections import OrderedDict
@@ -11,18 +11,18 @@
1111

1212

1313
class CompletionRefresher(object):
14-
refreshers: Dict[str, Callable] = OrderedDict()
14+
refreshers: dict[str, Callable] = OrderedDict()
1515

1616
def __init__(self) -> None:
17-
self._completer_thread: Optional[threading.Thread] = None
17+
self._completer_thread: threading.Thread | None = None
1818
self._restart_refresh = threading.Event()
1919

2020
def refresh(
2121
self,
2222
executor: SQLExecute,
23-
callbacks: Callable | List[Callable],
24-
completer_options: Optional[dict] = None,
25-
) -> List[Tuple]:
23+
callbacks: Callable | list[Callable],
24+
completer_options: dict | None = None,
25+
) -> list[tuple]:
2626
"""Creates a SQLCompleter object and populates it with the relevant
2727
completion suggestions in a background thread.
2828
@@ -61,7 +61,7 @@ def is_refreshing(self) -> bool:
6161
def _bg_refresh(
6262
self,
6363
sqlexecute: SQLExecute,
64-
callbacks: Callable | List[Callable],
64+
callbacks: Callable | list[Callable],
6565
completer_options: dict,
6666
) -> None:
6767
completer = SQLCompleter(**completer_options)
@@ -97,7 +97,7 @@ def _bg_refresh(
9797
callback(completer)
9898

9999

100-
def refresher(name: str, refreshers: Dict[str, Callable] = CompletionRefresher.refreshers):
100+
def refresher(name: str, refreshers: dict[str, Callable] = CompletionRefresher.refreshers):
101101
"""Decorator to add the decorated function to the dictionary of
102102
refreshers. Any function decorated with a @refresher will be executed as
103103
part of the completion refresh routine."""

litecli/config.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import os
66
import platform
77
from os.path import expanduser, exists, dirname
8-
from typing import Optional
8+
99

1010
from configobj import ConfigObj
1111

@@ -20,7 +20,7 @@ def config_location() -> str:
2020
return expanduser("~/.config/litecli/")
2121

2222

23-
def load_config(usr_cfg: str, def_cfg: Optional[str] = None) -> ConfigObj:
23+
def load_config(usr_cfg: str, def_cfg: str | None = None) -> ConfigObj:
2424
cfg = ConfigObj()
2525
if def_cfg:
2626
cfg.merge(ConfigObj(def_cfg, interpolation=False))
@@ -52,7 +52,7 @@ def upgrade_config(config: str, def_config: str) -> None:
5252
cfg.write()
5353

5454

55-
def get_config(liteclirc_file: Optional[str] = None) -> ConfigObj:
55+
def get_config(liteclirc_file: str | None = None) -> ConfigObj:
5656
from litecli import __file__ as package_root
5757

5858
package_root = os.path.dirname(package_root)

litecli/main.py

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
except ImportError:
1818
from sqlite3 import OperationalError, sqlite_version
1919
from time import time
20-
from typing import Any, Iterable, Optional, Dict
20+
from typing import Any, Iterable
2121

2222
import click
2323
import sqlparse
@@ -66,12 +66,12 @@ class LiteCli(object):
6666

6767
def __init__(
6868
self,
69-
sqlexecute: Optional[SQLExecute] = None,
70-
prompt: Optional[str] = None,
71-
logfile: Optional[Any] = None,
69+
sqlexecute: SQLExecute | None = None,
70+
prompt: str | None = None,
71+
logfile: Any | None = None,
7272
auto_vertical_output: bool = False,
73-
warn: Optional[bool] = None,
74-
liteclirc: Optional[str] = None,
73+
warn: bool | None = None,
74+
liteclirc: str | None = None,
7575
) -> None:
7676
self.sqlexecute = sqlexecute
7777
self.logfile = logfile
@@ -190,7 +190,7 @@ def change_table_format(self, arg: str, **_: Any):
190190
msg += "\n\t{}".format(table_type)
191191
yield (None, None, None, msg)
192192

193-
def change_db(self, arg: Optional[str], **_: Any):
193+
def change_db(self, arg: str | None, **_: Any):
194194
if arg is None:
195195
self.sqlexecute.connect()
196196
else:
@@ -204,7 +204,7 @@ def change_db(self, arg: Optional[str], **_: Any):
204204
'You are now connected to database "%s"' % (self.sqlexecute.dbname),
205205
)
206206

207-
def execute_from_file(self, arg: Optional[str], **_: Any):
207+
def execute_from_file(self, arg: str | None, **_: Any):
208208
if not arg:
209209
message = "Missing required argument, filename."
210210
return [(None, None, None, message)]
@@ -220,7 +220,7 @@ def execute_from_file(self, arg: Optional[str], **_: Any):
220220

221221
return self.sqlexecute.run(query)
222222

223-
def change_prompt_format(self, arg: Optional[str], **_: Any):
223+
def change_prompt_format(self, arg: str | None, **_: Any):
224224
"""
225225
Change the prompt format.
226226
"""
@@ -279,7 +279,7 @@ def initialize_logging(self) -> None:
279279
root_logger.debug("Initializing litecli logging.")
280280
root_logger.debug("Log file %r.", log_file)
281281

282-
def read_my_cnf_files(self, keys: Iterable[str]) -> Dict[str, Optional[str]]:
282+
def read_my_cnf_files(self, keys: Iterable[str]) -> dict[str, str | None]:
283283
"""
284284
Reads a list of config files and merges them. The last one will win.
285285
:param files: list of files to read
@@ -661,7 +661,7 @@ def echo(self, s: str, **kwargs: Any) -> None:
661661
self.log_output(s)
662662
click.secho(s, **kwargs)
663663

664-
def get_output_margin(self, status: Optional[str] = None) -> int:
664+
def get_output_margin(self, status: str | None = None) -> int:
665665
"""Get the output margin (number of rows for the prompt, footer and
666666
timing message."""
667667
margin = self.get_reserved_space() + self.get_prompt(self.prompt_format).count("\n") + 2
@@ -670,7 +670,7 @@ def get_output_margin(self, status: Optional[str] = None) -> int:
670670

671671
return margin
672672

673-
def output(self, output: Iterable[str], status: Optional[str] = None) -> None:
673+
def output(self, output: Iterable[str], status: str | None = None) -> None:
674674
"""Output text to stdout or a pager command.
675675
676676
The status text is not outputted to pager or files.

litecli/packages/completion_engine.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
from __future__ import annotations
22

3-
from typing import Any, Dict, List, Optional
3+
from typing import Any
44

55
import sqlparse
66
from sqlparse.sql import Comparison, Identifier, Where, Token
77
from .parseutils import last_word, extract_tables, find_prev_keyword
88
from .special import parse_special_command
99

1010

11-
def suggest_type(full_text: str, text_before_cursor: str) -> List[Dict[str, Any]]:
11+
def suggest_type(full_text: str, text_before_cursor: str) -> list[dict[str, Any]]:
1212
"""Takes the full_text that is typed so far and also the text before the
1313
cursor to suggest completion type and scope.
1414
@@ -18,7 +18,7 @@ def suggest_type(full_text: str, text_before_cursor: str) -> List[Dict[str, Any]
1818

1919
word_before_cursor = last_word(text_before_cursor, include="many_punctuations")
2020

21-
identifier: Optional[Identifier] = None
21+
identifier: Identifier | None = None
2222

2323
# here should be removed once sqlparse has been fixed
2424
try:
@@ -87,7 +87,7 @@ def suggest_type(full_text: str, text_before_cursor: str) -> List[Dict[str, Any]
8787
return suggest_based_on_last_token(last_token, text_before_cursor, full_text, identifier)
8888

8989

90-
def suggest_special(text: str) -> List[Dict[str, Any]]:
90+
def suggest_special(text: str) -> list[dict[str, Any]]:
9191
text = text.lstrip()
9292
cmd, _, arg = parse_special_command(text)
9393

@@ -144,11 +144,11 @@ def _expecting_arg_idx(arg: str, text: str) -> int:
144144

145145

146146
def suggest_based_on_last_token(
147-
token: Optional[str | Token],
147+
token: str | Token | None,
148148
text_before_cursor: str,
149149
full_text: str,
150-
identifier: Optional[Identifier],
151-
) -> List[Dict[str, Any]]:
150+
identifier: Identifier | None,
151+
) -> list[dict[str, Any]]:
152152
if isinstance(token, str):
153153
token_v = token.lower()
154154
elif isinstance(token, Comparison):
@@ -169,7 +169,7 @@ def suggest_based_on_last_token(
169169
else:
170170
token_v = token.value.lower()
171171

172-
def is_operand(x: Optional[str]) -> bool:
172+
def is_operand(x: str | None) -> bool:
173173
return bool(x) and any([x.endswith(op) for op in ["+", "-", "*", "/"]])
174174

175175
if not token:
@@ -328,5 +328,5 @@ def is_operand(x: Optional[str]) -> bool:
328328
return [{"type": "keyword"}]
329329

330330

331-
def identifies(id: Any, schema: Optional[str], table: str, alias: Optional[str]) -> bool:
331+
def identifies(id: Any, schema: str | None, table: str, alias: str | None) -> bool:
332332
return id == alias or id == table or (schema and (id == schema + "." + table))

litecli/packages/filepaths.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,18 @@
11
# -*- coding: utf-8
22
from __future__ import annotations
33

4-
from typing import List, Tuple
54

65
import os
76

87

9-
def list_path(root_dir: str) -> List[str]:
8+
def list_path(root_dir: str) -> list[str]:
109
"""List directory if exists.
1110
1211
:param dir: str
1312
:return: list
1413
1514
"""
16-
res: List[str] = []
15+
res: list[str] = []
1716
if os.path.isdir(root_dir):
1817
for name in os.listdir(root_dir):
1918
res.append(name)
@@ -38,7 +37,7 @@ def complete_path(curr_dir: str, last_dir: str) -> str | None:
3837
return None
3938

4039

41-
def parse_path(root_dir: str) -> Tuple[str, str, int]:
40+
def parse_path(root_dir: str) -> tuple[str, str, int]:
4241
"""Split path into head and last component for the completer.
4342
4443
Also return position where last component starts.
@@ -54,7 +53,7 @@ def parse_path(root_dir: str) -> Tuple[str, str, int]:
5453
return base_dir, last_dir, position
5554

5655

57-
def suggest_path(root_dir: str) -> List[str]:
56+
def suggest_path(root_dir: str) -> list[str]:
5857
"""List all files and subdirectories in a directory.
5958
6059
If the directory is not specified, suggest root directory,

litecli/packages/parseutils.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
from __future__ import annotations
22

33
import re
4-
from typing import Generator, Iterable, Optional, Tuple, List, Dict
4+
from typing import Generator, Iterable
55

66
import sqlparse
77
from sqlparse.sql import IdentifierList, Identifier, Function, Token, TokenList
88
from sqlparse.tokens import Keyword, DML, Punctuation
99

10-
cleanup_regex: Dict[str, re.Pattern[str]] = {
10+
cleanup_regex: dict[str, re.Pattern[str]] = {
1111
# This matches only alphanumerics and underscores.
1212
"alphanum_underscore": re.compile(r"(\w+)$"),
1313
# This matches everything except spaces, parens, colon, and comma
@@ -120,7 +120,7 @@ def extract_from_part(parsed: TokenList, stop_at_punctuation: bool = True) -> Ge
120120
break
121121

122122

123-
def extract_table_identifiers(token_stream: Iterable[Token]) -> Generator[Tuple[Optional[str], str, Optional[str]], None, None]:
123+
def extract_table_identifiers(token_stream: Iterable[Token]) -> Generator[tuple[str | None, str, str | None], None, None]:
124124
"""Yield tuples of (schema_name, table_name, table_alias)."""
125125

126126
for item in token_stream:
@@ -149,7 +149,7 @@ def extract_table_identifiers(token_stream: Iterable[Token]) -> Generator[Tuple[
149149

150150

151151
# extract_tables is inspired from examples in the sqlparse lib.
152-
def extract_tables(sql: str) -> List[Tuple[Optional[str], str, Optional[str]]]:
152+
def extract_tables(sql: str) -> list[tuple[str | None, str, str | None]]:
153153
"""Extract the table names from an SQL statement.
154154
155155
Returns a list of (schema, table, alias) tuples
@@ -168,7 +168,7 @@ def extract_tables(sql: str) -> List[Tuple[Optional[str], str, Optional[str]]]:
168168
return list(extract_table_identifiers(stream))
169169

170170

171-
def find_prev_keyword(sql: str) -> Tuple[Optional[Token], str]:
171+
def find_prev_keyword(sql: str) -> tuple[Token | None, str]:
172172
"""Find the last sql keyword in an SQL statement
173173
174174
Returns the value of the last keyword, and the text of the query with

0 commit comments

Comments
 (0)