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

Check which attributes have been loaded without triggering imports #51

Open
lagru opened this issue Apr 13, 2023 · 9 comments
Open

Check which attributes have been loaded without triggering imports #51

lagru opened this issue Apr 13, 2023 · 9 comments
Labels
type: Enhancement New feature or request

Comments

@lagru
Copy link
Member

lagru commented Apr 13, 2023

Is there a mechanism to check which objects have been loaded and which ones are still in the "lazy" state? Looking through the code and inspecting the objects returned by lazy.attach_stub it didn't see an obvious way to do so.

Maybe this could be addressed by making attach not return simple functions but objects. E.g.

__getattr__, __dir__, _ = lazy.attach_stub(__name__, __file__)
__getattr__.loaded_names  # return names which were already loaded

I think this would be very helpful in debugging and testing that lazy loading actually works as intended.

I'd be happy to work on this if there is interest!

@lagru
Copy link
Member Author

lagru commented Apr 13, 2023

Inspecting sys.modules might help with some cases. Though, it is less explicit than checking an object which remembers which attributes were accessed.

@stefanv
Copy link
Member

stefanv commented Apr 13, 2023

You could also just attach that dict to the function itself.

In [3]: def __get__(x):
   ...:     return x
   ...:

In [4]: __get__.__loaded = ['foo']

In [5]: __get__.__loaded
Out[5]: ['foo']

Question is, who will be looking at that. Perhap it can be done only when a debug flag is present in the environment.

@lagru
Copy link
Member Author

lagru commented Apr 13, 2023

Hmm, attach creates a new __getattr__() as a closure for each call, so I guess this would work. Though, it feels very hacky to me. We do have classes to combine logic and state. A simple class with __call__ and __repr__ seems like the saner and more flexible architectural choice to me. 😅

Good point about the debug flag. I guess the bigger question is how to reliably and automatically test that accidental imports don't invalidate lazy loading. Basically I'd like something to turn red and notice if a PR triggers an import in scikit-image.

@stefanv
Copy link
Member

stefanv commented Apr 13, 2023

If that's all you want to do, then you can just add a check to getattr that raises if a certain env variable is set, or if you're inside a certain context manager.

@stefanv
Copy link
Member

stefanv commented Jan 25, 2024

I'm closing for now, since there's no obvious action to take.

@stefanv stefanv closed this as completed Jan 25, 2024
@lagru
Copy link
Member Author

lagru commented Jan 26, 2024

Could we re-open since there's your suggestion

you can just add a check to getattr that raises if a certain env variable is set, or if you're inside a certain context manager.

which I'd be happy to take on some time?

@stefanv stefanv reopened this Jan 26, 2024
@stefanv
Copy link
Member

stefanv commented Mar 15, 2024

@lagru I'm getting back to this issue; could you help me understand what kind of debugging you need to do? Is it sufficient to raise on getattr? That will only catch the first instance. Would logging be better?

@stefanv stefanv added the type: Enhancement New feature or request label Mar 15, 2024
@lagru
Copy link
Member Author

lagru commented Mar 16, 2024

Basically, I'd like to be able to test the assumption that nothing is loaded for a given import. I like your environment variable idea. What do you think about an API like this?

LAZY_LOADER_RAISE_ON=".*" python -c "import skimage"
LAZY_LOADER_RAISE_ON="skimage.restoration" python -c "import skimage.restoration"

LAZY_LOADER_RAISE_ON would tell lazy_loader to raise an error if it is requested to load something whose __qualname__ matches the regex. This approach seems reasonably simple to implement. If necessary this we could even add LAZY_LOADER_ALLOW for a very flexible blacklist / whitelist approach.

Ideally, I'd like to have an approach that could be called from within Python, but that would require a clean import slate for the current Python process. Could be done with subprocess but then it's no better than the approach above using env variables. What do you think?

@lagru
Copy link
Member Author

lagru commented Mar 16, 2024

Being able to check in the current console has "X" been imported would be a bonus that might help with debugging.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: Enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants