-
-
Notifications
You must be signed in to change notification settings - Fork 42
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
submodules overshadow imports of the same name #124
Comments
Yep, Griffe's data model has a flaw: it does not distinguish between a submodule named |
Any chance you could point to some of the places that would need to be tweaked? I don't mind taking a look, since griffe is making quartodoc's job a million times easier..! |
Well, currently submodules are stored in the |
Also, if we support that, we'll need to (re)introduce the colon |
Sorry for the long delay--I can definitely see how it creates a bit of complexity. Since griffe ends up keeping the module--which allows grabbing functions by their canonical path--it feels like the impact of overshadowing is not too bad. (I'd still love to pick this up at some point) |
@machow @patrick91 @NiklasRosenstein I started working on this. And, to be honest, I'm very tempted to leave things as they are and mark this as "won't fix". Without going into details, Python itself can be very confusing:
# pkg/b/__init__.py
c = 1 # pkg/b/c.py
d = 1 >>> from pkg import b
>>> b.c
1
>>> from pkg.b.c import d # import pkg.b.c has the same effect
>>> b.c
<module 'pkg.b.c' from '/home/pawamoy/t/pkg/b/c.py'> Boom, Python just shadowed the member too. Just because of that, I'm very much inclined to declare the practice of using the same name for both a member and a submodule a bad practice. Now, even if we were to re-introduce colons in the path syntax (
# pkg/a.py
from pkg import b Python itself refuses to "pass through b" when it is an alias: >>> from pkg.a.b import c
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'pkg.a.b'; 'pkg.a' is not a package So, how would we write this path in Griffe?
Or should we stick with On the implementation side, supporting colons in object paths bring a lot of complexity, while it's already quite complex. To conclude, I'm -1 on supporting this, and +1 to document this limitation prominently, as well as taking a stance and saying this is bad practice anyway. |
While writing docs, I've ran more experiments, and it turns out that shadowing via import is less bad. With the same file tree, but these contents: # pkg/b/__init__.py
from pkg.b.c import c # pkg/b/c.py
def c(): ... ...we get this behavior: >>> from pkg import b
>>> b.c
<function thing at 0x78ae45e3a0c0>
>>> from pkg.b.c import c
>>> b.c
<function thing at 0x78ae45e3a0c0> # still the function and not the module
>>> import pkg.b.c
>>> pkg.b.c
<function thing at 0x78ae45e3a0c0> # even like this In that case I'd say we could at least give precedence to the imported object rather than the submodule, since the intent is to expose the object. But even then I still find all that confusing: somehow importing makes things OK, but declaring can make the submodule shadow the object. |
If a module's
__init__.py
has a submodule,foo.py
. Then importing a function of the same name from it, seems to keep the module name, rather than the function. This seems like a slight mismatch from dynamically importing, which keeps the function instead.Example files
some_package/__init__.py
some_package/foo.py
The text was updated successfully, but these errors were encountered: