Skip to content
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

change imports to from Y import X as X for compatibility with pyright --verifytypes #2629

Merged
merged 34 commits into from
Jun 9, 2023

Conversation

jakkdl
Copy link
Member

@jakkdl jakkdl commented Apr 5, 2023

Completes the first task in #2625

Should probably not be merged before a test for test_exports.py is written that checks that the exports seen by verifytypes is the same as the other static analyzers, and/or the CI check for type completeness.

remaining TODO:

  • make sure py.typed exists in tests.test_exports.test_static_tool...
  • save the new results from verifytypes in git in CI
  • get pyright to play along by setting PYRIGHT_FORCE_PYTHON_VERSION in all the places.

@jakkdl jakkdl force-pushed the import_x_as_x branch 2 times, most recently from 1348e3e to b4a46d5 Compare April 5, 2023 15:24
@codecov
Copy link

codecov bot commented Apr 5, 2023

Codecov Report

Merging #2629 (d007808) into master (bec7cc6) will increase coverage by 0.00%.
The diff coverage is 90.00%.

Additional details and impacted files
@@           Coverage Diff           @@
##           master    #2629   +/-   ##
=======================================
  Coverage   98.10%   98.11%           
=======================================
  Files         118      118           
  Lines       16471    16480    +9     
  Branches     2977     2983    +6     
=======================================
+ Hits        16159    16169   +10     
  Misses        255      255           
+ Partials       57       56    -1     
Impacted Files Coverage Δ
trio/abc.py 100.00% <ø> (ø)
trio/testing/__init__.py 0.00% <0.00%> (ø)
trio/__init__.py 100.00% <100.00%> (ø)
trio/_tests/test_exports.py 95.73% <100.00%> (+0.96%) ⬆️
trio/from_thread.py 100.00% <100.00%> (ø)
trio/lowlevel.py 100.00% <100.00%> (ø)
trio/socket.py 100.00% <100.00%> (ø)
trio/to_thread.py 100.00% <100.00%> (ø)

@A5rocks
Copy link
Contributor

A5rocks commented Apr 5, 2023

Funnily enough I also did this yesterday, though I see I did trio/socket and you didn't. (I'm not too sure if the as is necessary there TBF).

Also we re-export some symbols via from A import X as Y and I'm not sure how to make that work here.

URL: A5rocks@37bb8ed

@jakkdl
Copy link
Member Author

jakkdl commented Apr 6, 2023

Funnily enough I also did this yesterday, though I see I did trio/socket and you didn't. (I'm not too sure if the as is necessary there TBF).

Also we re-export some symbols via from A import X as Y and I'm not sure how to make that work here.

URL: A5rocks@37bb8ed

haha, good that it's mostly just some regex search&replace.

The as is only needed when you're re-exporting from a private module, so I intentionally skipped all the ones in socket - and one or two in the other files iirc. But a test_export test should settle it anyhow

trio/tests/verify_types.json Outdated Show resolved Hide resolved
trio/tests/test_exports.py Outdated Show resolved Hide resolved
trio/tests/verify_types.json Outdated Show resolved Hide resolved
trio/tests/verify_types.json Outdated Show resolved Hide resolved
@jakkdl
Copy link
Member Author

jakkdl commented Apr 10, 2023

whee, finally managed to wrangle CI to pass
.
Only thing left now is getting CI to save the changes in verify_types.json after running check_type_completeness in in this repo, or another repo, or somewhere else.

It seems there's a bunch of ways of doing that but idk what the setup with secrets and stuff is, and seems related to the discussion that went on in #2592 that stalled out when it got into complications around that.

@A5rocks
Copy link
Contributor

A5rocks commented Apr 11, 2023

Only thing left now is getting CI to save the changes in verify_types.json after running check_type_completeness in in this repo, or another repo, or somewhere else.

Why not make the test error when type completeness increases, telling the user to update the JSON file?

@jakkdl
Copy link
Member Author

jakkdl commented Apr 12, 2023

Only thing left now is getting CI to save the changes in verify_types.json after running check_type_completeness in in this repo, or another repo, or somewhere else.

Why not make the test error when type completeness increases, telling the user to update the JSON file?

ooh that's a simple solution. Me like!

@jakkdl
Copy link
Member Author

jakkdl commented Apr 12, 2023

That works, but only after #2628 has been merged - cause at least on my different environments I get different results for a bunch of symbols in trio.tests, possibly due to different python versions, which might make regenerating the json file a possible nightmare for some users if they've not been very careful with their virtual environments.

Copy link
Contributor

@A5rocks A5rocks left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor comments, will be happy to merge once you fix. I'll try to be much more responsive with types-specific PRs!

check.sh Show resolved Hide resolved
trio/__init__.py Show resolved Hide resolved
trio/__init__.py Show resolved Hide resolved
trio/_tests/check_type_completeness.py Outdated Show resolved Hide resolved
trio/_tests/check_type_completeness.py Outdated Show resolved Hide resolved
trio/_tests/test_exports.py Show resolved Hide resolved
if modname + "." in x.decode()
}

# don't require verifytypes to see reexported constants from socket
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I disagree with this comment but if it's annoying we can bump this off

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, trio.socket needs a similar treatment as trio.Path had to get the constants properly visible.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wait no. hmm

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems like pytest, similar to with __version__, ignores constants with the same name as those in socket (probably because we import from it?) - even when running --verbose. It seems to even ignore them when there's typing errors in them.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Type annotations can be omitted in a few specific cases where the type is obvious from the context:

  • ...
  • Constants that are assigned simple literal values (e.g. RED = '#F00' or MAX_TIMEOUT = 50 or room_temperature: Final = 20). A constant is a symbol that is assigned only once and is either annotated with Final or is named in all-caps. A constant that is not assigned a simple literal value requires explicit annotations, preferably with a Final annotation (e.g. WOODWINDS: Final[list[str]] = ['Oboe', 'Bassoon']).
    https://github.com/microsoft/pyright/blob/main/docs/typed-libraries.md#type-completeness

So it's plausibly a bug that they don't show up in --verbose or --outputjson, but it's intended that they're not covered by --verifytypes.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually no, it's the usual

Imported symbols are considered private by default. If they use the “import A as A” (a redundant module alias), “from X import A as A” (a redundant symbol alias), or “from . import A” forms, symbol “A” is not private unless the name begins with an underscore.

that hits here. So what'd need to be changed here is changing the huge list of imports from socket to be from socket import (X as X, Y as Y, Z as Z).

I don't think we care for this in terms of --verifytypes, but if somebody uses pyright as their type checker it will give an error of reportPrivateImportUsage when they try accessing it. That seems important enough to warrant making that huge bulk of an import statement even messier

Copy link
Contributor

@A5rocks A5rocks Jun 1, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm yeah, well it's a gigantic change so let's maybe sit on it a bit! Maybe an ad-hoc codemod would help out a ton, in combination with a run from black? Actually it's simple enough to find-and-replace, honestly. NVM

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

vim macros FTW :D

trio/_tests/test_exports.py Outdated Show resolved Hide resolved
trio/_timeouts.py Outdated Show resolved Hide resolved
trio/socket.py Outdated Show resolved Hide resolved
@jakkdl
Copy link
Member Author

jakkdl commented May 30, 2023

I have no clue why the omit isn't working in .coveragerc
EDIT: should be fixed by #2654

@jakkdl
Copy link
Member Author

jakkdl commented May 31, 2023

Okay, I think that's all comments addressed. The drop in codecov I think is solely due to #2645

@jakkdl jakkdl requested a review from A5rocks May 31, 2023 11:37
Comment on lines 128 to 144
new_symbols = []
# remove path & line/col references in errors
for symbol in current_result["typeCompleteness"]["symbols"]:
# filter out symbols with no errors
if not symbol["diagnostics"]:
continue
for diag in symbol["diagnostics"]:
del diag["file"]
diag.pop("range", None)
new_symbols.append(symbol)

current_result["typeCompleteness"]["symbols"] = new_symbols

with open(RESULT_FILE, "w") as file:
json.dump(current_result, file, sort_keys=True, indent=2)
# add newline at end of file so it's easier to manually modify
file.write("\n")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK I reread things and I kinda don't get why we keep symbols at all. I don't see them being used elsewhere, am I missing something? They're a gigantic list and probably most of the reason the file is as big as it is.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We initially removed it, but I realized when I was trying out stuff that without it you won't get any feedback if/when the check fails. The numbers will change, but unless you checkout previous revisions, manually run pyright --verifytypes, pipe into a file, and manually diff against a manual --verifytypes run on your PR - you're left guessing what symbol you broke where. And if your local environment differs from CI, then you're absolutely toast. (I have recurring problems with CI not giving same results as running stuff in my virtualenv and/or tox envs)

I could shorten the file further, removing more info that's probably redundant, not pretty-print it - or like dump symbols into a compressed pickle that the script reads to say what symbols have changed, but:

  1. the json file is not included when packaging
  2. the json file will likely drop down in size a lot early on as I do a first pass and introduce a lot of trivial typing on functions.

If you still think it's a problem, I'll make a pass at sizing it down. Or I can toss symbols out for now, run the script modified locally, and after (2) when the file is smaller add it to the repo.

Other esoteric options include commiting the file to a different branch, git-annex, have it in a submodule...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, my concern is that we're making the repository larger for anyone who wants a (full) clone. Do you have measurements of the .git folder before and after this? (You may want to rebase first to get rid of the old much bigger json file)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like going from something like 7.9M -> 8.1M
But it's a good point, I hadn't realized that big files will stick around forever in the history. I'll test pruning it down to being just a list of symbols with no extra info

@jakkdl
Copy link
Member Author

jakkdl commented Jun 1, 2023

decided to go back to running with --ignoreexternal - while some symbols were stuff that should be fixed, a lot of it was it complaining about the hacky imports in trio.socket and similar low prio stuff. #FutureProblem

@jakkdl jakkdl requested a review from A5rocks June 5, 2023 15:49
Copy link
Contributor

@A5rocks A5rocks left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this looks good? I'll review in slightly more detail once this is rebased!

@jakkdl
Copy link
Member Author

jakkdl commented Jun 6, 2023

@A5rocks merged main

Copy link
Contributor

@A5rocks A5rocks left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good overall, small little nitpicks.

trio/__init__.py Outdated Show resolved Hide resolved
ci.sh Show resolved Hide resolved
trio/_tests/check_type_completeness.py Outdated Show resolved Hide resolved
trio/_tests/check_type_completeness.py Outdated Show resolved Hide resolved

print("*" * 20)

return int(failed)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bool is a subclass of int so this isn't necessary. But maybe nice for clarity? Dunno.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

haha, I guess it's my c++ programming leaking. But yeah I don't mind the int conversion

trio/socket.py Outdated
# all these constants, but it lets static analysis tools understand what's
# going on. There's a test in test_exports.py to make sure that the list is
# kept up to date.
try:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should put this in an if TYPE_CHECKING block? But eh, I guess it does literally say "It always fails at runtime" and I don't know how this might change tools other than type checkers. Ig we can push this change off if you want!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks like jedi doesn't care, so switching it to be a TYPE_CHECKING block instead.

Copy link
Contributor

@A5rocks A5rocks left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, quickly glanced through and didn't see anything! If tests pass, feel free to merge this after making commit history more succinct.

@jakkdl jakkdl merged commit 493c915 into python-trio:master Jun 9, 2023
@jakkdl
Copy link
Member Author

jakkdl commented Jun 9, 2023

🎉 🎉 🚀 🚀 🚀

@jakkdl jakkdl deleted the import_x_as_x branch June 9, 2023 11:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants