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

detection of program name when run with python -m #1603

Closed
davidism opened this issue Jun 25, 2020 · 5 comments · Fixed by #1609
Closed

detection of program name when run with python -m #1603

davidism opened this issue Jun 25, 2020 · 5 comments · Fixed by #1609
Assignees
Milestone

Comments

@davidism
Copy link
Member

davidism commented Jun 25, 2020

The program name (referred to as prog_name or info_name) is the name Click uses in usage help text. If it's not specified, Click tries to detect it by looking at sys.argv[0].

click/src/click/core.py

Lines 797 to 800 in dfb842d

if prog_name is None:
prog_name = make_str(
os.path.basename(sys.argv[0] if sys.argv else __file__)
)

This works when the CLI is run as a script, either directly, or indirectly as an entry point, or as a module when the program is a single file, but fails when the program is a package and run with python -m. In that case, Python converts the -m name to the Python file within the package that would be executed. (The use of __file__ there is also incorrect, as that will always point to click/core.py. There should never be a case where sys.argv is empty. make_str is probably not needed either.)

This leads to the following names:

  • python example.py, executing a script directly - example.py
  • python -m example, the single file module example.py - example.py
  • python -m example, a package like example/__main__.py - __main__.py
  • python -m example.cli, a submodule like example/cli.py - cli.py
  • example, an entry point, with any of the layouts above - example

What's usually expected is that executing a script will print the Python file name (example.py), executing an entry point will print the entry point name (example), and executing a module or package will print the Python command (python -m example, python -m example.cli)

This leads to projects that expect to be run as either an entry point or -m writing their own wrapper around the CLI to control what name gets used. For example, Flask uses a wrapper that the entry point will call with no args, while __main__.py or __name__ == "__main__" will pass as_module=True.

def main(as_module=False):
    cli.main(prog_name="python -m flask" if as_module else None)

Unfortunately, detecting whether python -m was used is really, really complicated. Luckily, I did the work already in Werkzeug's reloader: https://github.com/pallets/werkzeug/blob/102bcda52176db448d383a9ef1ccf7e406a379eb/src/werkzeug/_reloader.py#L59. It won't be quite the same in Click because we're not concerned with the exact path to the python command or script file, or with arguments, but that should be a good start. Write a function detect_program_name() to detect this and call it in place of the existing code.

@kbanc
Copy link
Contributor

kbanc commented Jun 25, 2020

I'll look into this!

@davidism davidism added this to the 8.0.0 milestone Jun 25, 2020
@davidism
Copy link
Member Author

One more note, there is Windows-specific behavior here, so remember to test the fix against the different cases listed above on both Linux/Mac and Windows.

@davidism
Copy link
Member Author

davidism commented Jun 25, 2020

Here's a simple project to test out the commands with. example.tar.gz

$ tar xf example.tar.gz
$ cd example
$ python3 -m venv venv
$ . venv/bin/activate
$ pip install -e ../click  # wherever your click repo is
$ pip install -e .

Now you can do different commands and changes you make to your click repo will be reflected. The command echos the detected program name.

$ python -m example
$ python -m example.cli
$ example
$ python single.py
$ python -m single

@ovezovs
Copy link
Contributor

ovezovs commented Jun 26, 2020

I'll look into this!

One more note, there is Windows-specific behavior here, so remember to test the fix against the different cases listed above on both Linux/Mac and Windows.

I was reading the issue and saw that there may be a need for testing on windows. If you need someone with a windows machine, let me know. I know a lot of people use linux/mac.

@gmelodie
Copy link
Contributor

@ovezovs thanks! @kbanc set up a windows VM and got it done :)

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Nov 13, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants