scientific-python / lazy-loader

Populate library namespace without incurring immediate import costs
BSD 3-Clause "New" or "Revised" License
116 stars 19 forks source link

`lazy_loader.attach_stub` confuses submodule and function of the same name #54

Open lagru opened 1 year ago

lagru commented 1 year ago

At scikit-image, we are seeing that if a submodule and lazy loaded function have the same name, the module is unexpectedly imported instead. This behavior in the case of rolling_ball can be seen in https://github.com/scikit-image/scikit-image/pull/7021, https://github.com/scikit-image/scikit-image/pull/7021/commits/079962fc005cc853c20db243bcbb6a3558c4a62c, failing CI example.

What I find confusing that this does not happen for all jobs, though I haven't figured out a common denominator between the passing and failing group respectively. :thinking:

Our approach has been to rename the submodule but this may hint at a deeper issue / limitation / quirk in lazy_loader?

lagru commented 1 year ago

You even check for this case in https://github.com/scientific-python/lazy_loader/blob/a6188ac0a4dee20edc6fab099e606b19148de0d4/lazy_loader/__init__.py#L79-L84

Unfortunately I can't reproduce this locally yet to check what is going wrong...

stefanv commented 5 months ago

I suspect this is the following documented issue: https://scientific-python.org/specs/spec-0001/#caveats

stefanv commented 3 months ago

@lagru Did this happen inside of a doctest? The logs are unfortunately no longer accessible for me to check.

lagru commented 3 months ago

Yeah, we are in luck. Building and testing https://github.com/scikit-image/scikit-image/commit/079962fc005cc853c20db243bcbb6a3558c4a62c still works with the current dev environment. I changed the name of back to rolling_ball.py and reproduce the error with spin test -- --doctest-modulesskimage/restoration/rolling_ball.py

_______________________ [doctest] skimage.restoration.rolling_ball.rolling_ball _______________________
059     .. [1] Sternberg, Stanley R. "Biomedical image processing." Computer 1
060            (1983): 22-34. :DOI:`10.1109/MC.1983.1654163`
061
062     Examples
063     --------
064     >>> import numpy as np
065     >>> from skimage import data
066     >>> from skimage.restoration import rolling_ball
067     >>> image = data.coins()
068     >>> background = rolling_ball(data.coins())
UNEXPECTED EXCEPTION: TypeError("'module' object is not callable")
Traceback (most recent call last):
File "~/.local/lib/micromamba/envs/skidev312/lib/python3.12/doctest.py", line 1357, in __run
exec(compile(example.source, filename, "single",
File "<doctest skimage.restoration.rolling_ball.rolling_ball[4]>", line 1, in <module>
TypeError: 'module' object is not callable
~/Res/scikit-image/skimage/restoration/rolling_ball.py:68: UnexpectedException

Can also be reproduced on current main after renaming back to rolling_ball.py.