So, to rephrase your request,
you want argparse.ArgumentParser.prog to contain "{sys.executable} -m
{modulename}" so that the help text correctly indicates that it was invoked
that way?

PEP notes:

- POSIX only is maybe not a good strategy
- Can cmdline contain other unescaped \0's?
- This would be a sight performance regression for the most common cases.
(__main__.py is typically only used by stdlib modules; which is what it was
added for)

Solutions / workarounds:

- console_script entry_points

- How does pip make this work?
  When I run `python -u -m pip -h` it prints `{sys.executable} -m pip` as
the progname under usage (with *optparse*)

- Is this platform portable? Does __package__ always contain the correct
module name?

    prog = None
    if os.path.basename(sys.argv[0]) == "__main__.py":
        prog = f"{sys.executable} -m {__package__}"

...

- thecode.py (prog=...)
- output from `!examplecli -h` and `!python -m example -h`

# Python packaging, setup.py, console_scripts entrypoints, and \_\_main__.py

- Source:
  https://github.com/westurner/setuptoolsexample
- Read-only GitHub notebook view:
  https://github.com/westurner/setuptoolsexample/blob/master/examplenb.ipynb
- Read-only Nbviewer notebook view:

https://nbviewer.jupyter.org/github/westurner/setuptoolsexample/blob/master/examplenb.ipynb
- Read/Write mybinder.org (BinderHub (repo2docker)) notebook:

https://mybinder.org/v2/gh/westurner/setuptoolsexample/master?filepath=examplenb.ipynb

References:
-
https://python-packaging.readthedocs.io/en/latest/command-line-scripts.html#the-console-scripts-entry-point


```python
!rm -rf ./example.egg-info/
!ls **
```

    examplenb.ipynb  requirements.txt  setup.py

    example:
    __init__.py  __main__.py  __pycache__  thecode.py



```python
!cat setup.py
```


    from setuptools import setup

    setup(name='example',
          version='0.1',
          description='Example',
          url='http://github.com/.../...',
          author='Example',
          author_email='[email protected]',
          license='...',
          packages=['example'],
          zip_safe=False,
          entry_points={
              'console_scripts': [
                  'examplecli = example.thecode:main'
              ]}
          )



```python
!cat example/thecode.py
```


    import argparse
    import os
    import sys


    def main(argv=None):
        if argv is None:
            argv = sys.argv
        print("argv:", argv)

        prog = None
        if os.path.basename(sys.argv[0]) == "__main__.py":
            prog = f"{sys.executable} -m {__package__}"

        prs = argparse.ArgumentParser(prog=prog)
        prs.parse_args()


```python
!cat example/__main__.py
```


    import sys

    from .thecode import main

    def othermain():
        print("othermain")
        return main(sys.argv)

    if __name__ == "__main__":
        othermain()



```python
!cat ./requirements.txt
```

    -e .



```python
!pip install -r ./requirements.txt
# (this is equivalent to `pip install -e .`)
```

    Obtaining file:///home/user/-wrk/-ve37/sexample/src/sexample (from -r
./requirements.txt (line 1))
    Installing collected packages: example
      Found existing installation: example 0.1
        Uninstalling example-0.1:
          Successfully uninstalled example-0.1
      Running setup.py develop for example
    Successfully installed example



```python
!ls **
```

    examplenb.ipynb  requirements.txt  setup.py

    example:
    __init__.py  __main__.py  __pycache__  thecode.py

    example.egg-info:
    dependency_links.txt  not-zip-safe  SOURCES.txt
    entry_points.txt      PKG-INFO    top_level.txt



```python
# This is generated when you `pip install -e`
!cat ./example.egg-info/entry_points.txt
```

    [console_scripts]
    examplecli = example.thecode:main




```python
!ls ../../bin/
```

    activate  jsonschema    pip3
    activate.csh  jupyter    pip3.7
    activate.fish  jupyter-bundlerextension  postactivate
    activate.ps1  jupyter-kernel    postdeactivate
    activate_this.py  jupyter-kernelspec    preactivate
    activate.xsh  jupyter-migrate    predeactivate
    easy_install  jupyter-nbconvert    pygmentize
    easy_install-3.7  jupyter-nbextension    python
    examplecli  jupyter-notebook    python3
    get_env_details   jupyter-run    python3.7
    iptest  jupyter-serverextension   python-config
    iptest3  jupyter-troubleshoot    wheel
    ipython  jupyter-trust
    ipython3  pip



```python
!cat ../../bin/examplecli
```

    #!/home/user/-wrk/-ve37/sexample/bin/python3
    # EASY-INSTALL-ENTRY-SCRIPT: 'example','console_scripts','examplecli'
    __requires__ = 'example'
    import re
    import sys
    from pkg_resources import load_entry_point

    if __name__ == '__main__':
        sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
        sys.exit(
            load_entry_point('example', 'console_scripts', 'examplecli')()
        )



```python
# this runs the 'example' console_scripts entry_point
!examplecli -h
```

    argv: ['/home/user/-wrk/-ve37/sexample/bin/examplecli', '-h']
    usage: examplecli [-h]

    optional arguments:
      -h, --help  show this help message and exit



```python
# this runs example/__main__
!python -m example -h
```

    othermain
    argv:
['/home/user/-wrk/-ve37/sexample/src/sexample/example/__main__.py', '-h']
    usage: /home/user/-wrk/-ve37/sexample/bin/python -m example [-h]

    optional arguments:
      -h, --help  show this help message and exit





On Saturday, August 24, 2019, Michael Hooreman <[email protected]> wrote:

> Indeed.
>
> I usually do a workflow which makes my needs compatible with the
> standards, but I've started this when I was a python beginner.
>
> I'm aware since months that I should use setuptools, but it was not on my
> priority, because that bad decision had no impact. Now, time to change had
> come...
>
> Maybe one suggestion: I think it would be great to document it as a
> limitation in argparse. Don't you think?
>
> Regarding a "patching lib", I don't plan to add anything to pip until I
> found a portable solution. Sorry if my message was incorrect.
>
> Thanks again to everyone.
>
> Le sam. 24 août 2019 23:20, Andrew Barnert <[email protected]> a écrit :
>
>> On Aug 24, 2019, at 13:16, Michael Hooreman <[email protected]> wrote:
>> >
>> > I'll consider what you say, and try to understand what entrypoint is. I
>> have understood entrypoint as a wording for an entry point (main) script.
>> Sorry.
>>
>> Well, it _is_ that, but the point is that setuptools can auto-generate
>> those main scripts for you, without making you rearrange any of your code.
>> Which is very cool, and it’s a shame more people don’t know how to use it.
>>
>> > I just hope that I won't have to spend days on adapting my workflow,
>> but well, that's life.
>>
>> In your case, hours adapting your scripts to munge the usage output might
>> well be a better use of your time than days learning a new tool and
>> adapting your workflow to it.
>>
>> That doesn’t mean we should necessarily change the stdlib of Python to
>> encourage more people to build workflows like yours in the future instead
>> of more easily-manageable ones. But it does mean that if a lot of people
>> are already in your situation, and there’s something that would help all of
>> them, a change could well be worth doing. That’s why I responded
>> specifically to your proposal, and only added the stuff about setuptools
>> entrypoints as an afterthought.
>>
>> Your proposal might well be useful—but not if it breaks all POSIX systems
>> but Linux, gives a prog that isn’t usable as a prog, etc. I raised those
>> issues to see if you have a solution (or if anyone else does).
>>
>> > [Private joke]
>> > I must say that I find disappointing to receive a "tell me what you
>> need, I'll explain how to not need that". We are all IT guys, and I also do
>> that. Now, I see what it is from the other side of the court :-)
>> > [End of private joke]
>>
>> Personally, I generally try to explain “Here’s how to do that” before
>> “Here’s how _not_ to do that.” Especially since “Here’s how to do that”
>> often illustrates what a huge pain it is to do that, which convinces people
>> better than just saying “Don’t do that.” :) But in this case, you already
>> had a solution to offer, so it’s not really the same thing.
>>
>
_______________________________________________
Python-ideas mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/[email protected]/message/C6XBDK52RBJLLCCTRM5MD4AELMZEJEZJ/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to