-
Notifications
You must be signed in to change notification settings - Fork 86
Type checking #233
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Type checking #233
Conversation
- Introduce packages/special/types.py with DBCursor Protocol - Add/ tighten type hints across special/, sqlcompleter, sqlexecute, clibuffer/toolbar/style, config, filepaths, lexer, completion_refresher, key_bindings - Remove remaining mypy ignore headers in special modules - Replace Any with concrete types where safe; improve TextIO handling - Fix utils.check_if_sqlitedotcommand to handle non-str inputs safely - Remove mycli references in comments and update docstrings - Minor refactors for clarity; ruff+mypy clean
…o implicit Optional, warn on Any). Note: run with --explicit-package-bases or via tox.
…py, and utils bug fix
…pline (Unreleased at top, succinct entries)
litecli/clistyle.py
Outdated
|
||
import logging | ||
from typing import Dict, List, Tuple |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When using import annotations
in Python 3.9, and for any later Python without the import, dict
, list
, and tuple
can be used in their lowercased forms, without importing from typing
.
@@ -1,3 +1,6 @@ | |||
# type: ignore |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this #type: ignore
needed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had added mypy: ignore-errors to all the files before I started. Looks like I left them in by mistake.
litecli/clitoolbar.py
Outdated
@@ -1,17 +1,19 @@ | |||
from __future__ import unicode_literals | |||
# mypy: ignore-errors |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is mypy: ignore-errors
doing for us?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had added mypy: ignore-errors to all the files before I started. Looks like I left them in by mistake.
litecli/config.py
Outdated
else: | ||
return expanduser("~/.config/litecli/") | ||
|
||
|
||
def load_config(usr_cfg, def_cfg=None): | ||
def load_config(usr_cfg: str, def_cfg: Optional[str] = None) -> ConfigObj: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
str | None
is preferred by most over Optional[str]
.
@@ -1,24 +1,31 @@ | |||
from __future__ import unicode_literals |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are a few changes here unrelated to type hinting.
litecli/packages/parseutils.py
Outdated
@@ -16,7 +27,7 @@ | |||
} | |||
|
|||
|
|||
def last_word(text, include="alphanum_underscore"): | |||
def last_word(text: str, include: str = "alphanum_underscore") -> str: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The type of include
could even be a Literal
of the keys of cleanup_regex
.
@@ -187,7 +207,7 @@ def list_indexes(cur, arg=None, arg_type=PARSED_QUERY, verbose=False): | |||
aliases=("\\s",), | |||
case_sensitive=True, | |||
) | |||
def status(cur, **_): | |||
def status(cur: DBCursor, **_: Any) -> List[Tuple]: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As a matter of style, there isn't much purpose in typing **_: Any
. But it does no harm.
|
||
log = logging.getLogger(__name__) | ||
|
||
|
||
@export | ||
def set_favorite_queries(config): | ||
def set_favorite_queries(config: Any) -> None: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is Any
the best we can do for config
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was looking at mycli for this and it wasn't typed so I just went to Any.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would highly recommend replacing the capitalized versions of types with lowercased versions for builtins such as tuple
. Python 3.9 will be EOL soon, and we even can remove from __future__ import annotations
if support for 3.9 is removed.
Replace Dict, List, Tuple with dict, list, tuple. Replace Optional[str] with str | None.
I will take a look at this pr over the weekend. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm as a first step to introduce the type hints. We can improve over time 👍🏾
from prompt_toolkit.application import get_app | ||
|
||
|
||
def cli_is_multiline(cli): | ||
def cli_is_multiline(cli: Any) -> Filter: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand sometimes types can be complicated to express so Any
is preferred. Is it possible to add type here? If not documenting reason to use Any
can be useful later to replace it with better type. I suspect cli by default is of the type, Any
.
@@ -32,10 +41,11 @@ def refresh(self, executor, callbacks, completer_options=None): | |||
self._restart_refresh.set() | |||
return [(None, None, None, "Auto-completion refresh restarted.")] | |||
else: | |||
if executor.dbname == ":memory:": | |||
if executor.dbname == ":memory": |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This one seems non-type change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we use something like executor.dbname.startswith(":memory")
?
* False if the query is destructive and the user doesn't want to proceed. | ||
def convert(self, value: bool | str, param: click.Parameter | None, ctx: click.Context | None) -> bool: | ||
if isinstance(value, bool): | ||
return bool(value) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can just return value right like return value
right?
@@ -1,3 +1,5 @@ | |||
# mypy: ignore-errors |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a way to ignore all the errors in the directory rather than at each file in test directory?
Description
Add mypy based type checking.
Thanks to @rolandwalker for adding type hints to mycli. I've used that as inspiration and reference to do the same for litecli.
Checklist
CHANGELOG.md
file.