Closed ezragoss closed 3 years ago
So, came to a few conclusions:
This led to two conclusions:
But... seeing this made me realize that what name is, and what package is, can be a bit confusing. I think we can make things simpler / clearer if we switch our "checking" paradigm.
Currently, our paradigm is:
I think it will simplify things if:
This way, we're not having to worry about what we're looking for while we're doing the parsing, which simplifies that part... and when we're checking, we're checking against a "standardized format", which should simplify the checking portion too.
There's one other advantage to this approach - at some point, we'd like to switch to an approach where we go through and find all import statements, get their import info, and then cache out a big dictionary, indexed by the things we're looking for, and mapping to the available bindings. This will avoid a lot of unnecessary repeated "parsing" of import statements!
Oh, and the other thing I realized - right now, in type_by_import_stmt
, we search for (in order):
name_binding = find_import_info(name, root, package)
mod_binding = find_import_info(package, root, None)
The underlying reason is that, if we're looking for pkg.mod1.MyClass
, we want to prefer imports that bring MyClass
directly into the top-level namespace, over imports of just pkg.mod1
. However, since in our case we're always looking for classes/types - or, at the very least, things that are highly unlikely to be modules - this basically just means that we always prefer from X import Y
statements!
This is because, though this statement would make MyClass
available with a top-level binding:
import pkg.mod1.MyClass as theclass
...it's invalid unless MyClass
is a module, which it shouldn't be! So, the only way to bring in a type/class is with a from
statement.
So, we just prefer from
statements.
If we make our ImportInfo something like:
import pkg.mod1 as foobar => ImportInfo(pkg='pkg.mod1', entry=None, binding='foobar')
import pkg.mod1 => ImportInfo(pkg='pkg.mod1', entry=None, binding='pkg.mod1')
from pkg.mod1 import MyClass as thing => ImportInfo(pkg='pkg.mod1', entry='MyClass', binding='thing')
...then we're just looking for ImportInfo(pkg='pkg.mod1', entry='MyClass', ...)
first, followed by ImportInfo(pkg='pkg.mod1', entry=None, ...)
First - sorry for any noise I generated by addding :rocket: emoji - was using that as a way to mark comments that were addressed, until I realized that they can be hidden...
Anyway - I think nearly everything has been addressed, and all your latest changes looked great! There's only remaining thing I'd still like added - the 2nd test in this comment. It's just a new test, and I think it should work... but it will be a good test, both now and for any future regressions.
Assuming that passes, though, I think this PR is ready - it doesn't look like I have permissions to authorize the merge myself, so we may have to message Chad for that...
If a tool like
dmypy suggest
recommends,for the code
We used to incorrectly annotate
But we now correctly annotate