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

Circular import if script is called <module>.py #693

Closed
defnull opened this issue Sep 16, 2024 · 5 comments
Closed

Circular import if script is called <module>.py #693

defnull opened this issue Sep 16, 2024 · 5 comments

Comments

@defnull
Copy link

defnull commented Sep 16, 2024

Hi there, I'm trying to port an old project from setuptools (setup.py/cfg) to pyproject.toml and flit and hitting a wall with then generated script stub. Problem is: The script is called bottle.py and the module is called bottle. This breaks with an ImportError: cannot import name 'main' from partially initialized module 'bottle' (most likely due to a circular import) because the script-stub tries to import itself. This wasn't an issue with the old setuptools setup(..., scripts=['bottle.py']) approach because setuptools copied the entire module into the bin folder and the main method contained sys.modules.setdefault('bottle', sys.modules['__main__']). This worked because after bin/bottle.py was loaded as __main__, it copied itself into sys.modules['bottle'] and future imports for bottle would already find the initialized module and not search for it anymore.

I know this is use-case you probably to not want to support. Having a script with that name was a mistake I made a decode ago. I'm just asking if you perhaps have any idea how this could be worked around. Something I missed. I really do not want to break user scripts that rely on ./venv/bin/bottle.py to work.

@defnull defnull changed the title Control script generation Circular import if script is called <module>.py Sep 16, 2024
@defnull
Copy link
Author

defnull commented Sep 16, 2024

AFAIK it would be enough if I would be able to put files into /{distribution}-{version}.data/scripts/ inside the whl file with flit. This is what setuptools does for setup(..., scripts=['bottle.py']) or tool.setuptools.script-files = ['bottle.py'].

@takluyver
Copy link
Member

Hello! Thanks for bottle - while I haven't used it on anything in earnest, I recognise the name, and I have played around with it. 🙂

I think there's a Unix-specific way you could work around this by specifying an external data directory with your script at bin/bottle.py relative to that. That definitely won't work on Windows, but I don't think the scripts folder workaround you're describing would either- see pypa/pip#2596 .

@takluyver
Copy link
Member

You could also combine the workaround with a new command like bottle or bottlepy installed in the normal/modern way ([project.scripts]), and gradually encourage people to transition over to that. Pytest did something similar - the command use to be py.test and now it's pytest.

@defnull
Copy link
Author

defnull commented Sep 16, 2024

Good idea, I will try that. The more I think about it, the more I come to the conclusion that the only reasonable way forward is to get rid of bin/bottle.py completely and just call the script bottle. I'd like to have a grace period where calling bin/bottle.py prints a warning, but that might be tricky. Running python3 bottle.py or python3 -m bottle should not trigger the warning. I'll see if I can figure something out.

I'll close this issue as this is not a bug/issue with flit. Thanks for your help and kind words!

@defnull defnull closed this as completed Sep 16, 2024
@takluyver
Copy link
Member

Thanks!

You might be able to do something where a script bottle.py loads a helper module which does something like this:

import sys
from warnings import warn

warn("Deprecated bottle.py command, use python -m bottle instead")

if os.path.basename(sys.path[0]) in ('bin', 'Scripts'):
    del sys.path[0]

from bottle import *

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

No branches or pull requests

2 participants