-
Notifications
You must be signed in to change notification settings - Fork 64
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
Enable mypy review for pyshacl.cli:main and fix reported issues #192
Conversation
This patch updates the results of `mypy --ignore-missing-imports`, run only against `/pyshacl/cli.py`: | Count | Type-reviewed state | | ----- | --------------------------------- | | 0 | Current `master` branch state | | 40 | Only designating `main() -> None` | | 0 | Committed state | This patch updates the results of `mypy --ignore-missing-imports`, run against `/pyshacl`: | Count | Type-reviewed state | | ----- | --------------------------------------------- | | 20 | Current `master` branch state | | 61 | Only designating `main() -> None` in `cli.py` | | 21 | Committed state of `cli.py` | | 20 | Committed state including `main.py` | Signed-off-by: Alex Nelson <[email protected]>
I've noticed type review hasn't passed for a while. So I included in this PR evidence that the number of issues at least doesn't grow, while the type-annotated coverage does. |
if do_server: | ||
args = {} | ||
else: | ||
args = parser.parse_args() |
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 still needs to skip parse_args()
if the HTTP or SERVER env variables are set.
This is to allow the user to run PySHACL in server mode, without passing any cmdline arguments.
Normally omitting cmdline arguments will cause parse_args()
to throw it's missing arguments error.
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.
Restored, using an empty Namespace
object instead of an empty dictionary so args
has a more consistent type across both these branch sides.
@@ -183,16 +185,13 @@ def str_is_true(s_var: str): | |||
# parser.add_argument('-h', '--help', action="help", help='Show this help text.') | |||
|
|||
|
|||
def main(): | |||
def main() -> 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.
Should main()
be changed to return int
exit code, then pass that to sys.exit()
from the caller site? That would avoid all the sys.exit()
calls in here.
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.
At some point years ago, the idea wormed into my head that main()
in Python had to return None
.
However, I've had poor luck finding out where that idea came from. My current best guess is mypy
complaining about missing return signatures when I was first learning type annotations. E.g. from this program try.py
:
def main():
x = 1
x = "1"
if __name__ == "__main__":
main()
mypy try.py
returns no issues; fine & dandy, there's no typed context. mypy --strict
catches the error I want around x
, but gives this output about the rest:
try.py:1: error: Function is missing a return type annotation [no-untyped-def]
try.py:1: note: Use "-> None" if function does not return a value
try.py:3: error: Incompatible types in assignment (expression has type "str", variable has type "int") [assignment]
try.py:6: error: Call to untyped function "main" in typed context [no-untyped-call]
Found 3 errors in 1 file (checked 1 source file)
I thought there used to be a specific suggestion about main
instead of what's on the first 2 or last 1 lines. It might have just been me conflating nearby lines instead. I'm not finding a say on the matter in mypy
's documentation, PEPs on typing (483 and 484), or other search engine results.
Since mypy --strict
didn't complain at this:
from typing import Dict, Set
def main() -> Dict[str, Set[int]]:
return {"a": {1}}
if __name__ == "__main__":
main()
I'm fine swapping -> None
with anything else if you think it'll result in cleaner chaining.
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 started the "main
returns an int
" revision, and stopped partway through revising the sys.exit(2)
calls when I remembered another hint I had for why main
usually returns None
.
sys.exit(n)
influences the return status of the program call from main
. return n
doesn't.
E.g. here's a file try.py
:
def main() -> int:
print("I ran.")
return 1
main()
Here's the shell-visible exit status:
$ python3 try.py ; echo $?
I ran.
0
So I think the more shell-consistent idiom is to have the calls to sys.exit(main())
instead just be calls to main()
, and to leave any deeper-in-main
calls to sys.exit(n)
as they are now. I don't think having main() -> int
gains any control-flow advantage over sys.exit
doing hard-stops with a controlled exit status value, or raise SomethingUnfortunate
passing a traceback exit value 1 if uncaught.
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.
Checking back in on this thread: My own preference, in the general case for Python beyond this repository, is that main
should return None
, and anything meant to influence Python's exit status as non-0 should be handled with sys.exit()
or raise
.
I see the alternative "chaining into sys.exit
" style seems to be rooted in use of pyshacl.sh_http.cli()
. I'm guessing there are nuances, possibly for users outside this repository, of handling traceback
and control flow the way it's being handled there. So, I could understand you preferring pyshacl.cli.main() -> int
.
This seems like the last open review matter on this PR. Which is your preference - int
or None
for main
?
This patch also cleans away some typing symbols added when trying to make the "server mode" `args` variable work, but that became vestigial. Reported-by: Ashley Sommer <[email protected]> Signed-off-by: Alex Nelson <[email protected]>
I checked running Also, having caught up with the 0.24.0 release, this PR now appears to have no influence on the number of typing issues reported. So, the effect of the PR has become that type signatures are added. |
I believe after #223 is merged and this PR gets a catch-up merge, this PR will pass the |
Catch-up merge applied. |
Okay, I'm happy to merge this now |
Thank you! |
This is released now in PySHACL v0.26.0 |
This patch updates the results of
mypy --ignore-missing-imports
, run only against/pyshacl/cli.py
:master
branch statemain() -> None
This patch updates the results of
mypy --ignore-missing-imports
, run against/pyshacl
:master
branch statemain() -> None
incli.py
cli.py
main.py