-
Notifications
You must be signed in to change notification settings - Fork 89
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
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
| from __future__ import annotations | ||
|
|
||
| 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
|
|
||
|
|
||
| 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
|
|
||
|
|
||
| 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.
| 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.
|
|
||
| @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.
rolandwalker
left a comment
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. |
kracekumar
left a comment
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 👍🏾
|
|
||
|
|
||
| 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.
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'll have to come back to the use of Any and fix them up.
litecli/completion_refresher.py
Outdated
| 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")?
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.
Good catch. I'll fix it.
I don't think we could use startswith() here. I think it has to be an exact match.
litecli/packages/prompt_utils.py
Outdated
| * 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.mdfile.