Hello, We're currently using Pants version 2.16.0...
# general
b
Hello, We're currently using Pants version 2.16.0rc1 to build our Monorepo. A part of our codebase is a Python Click (version 8.1.3) CLI that we package as a pex_binary. We're trying to enable shell auto-completion with Click. However, according to the Click documentation, completion is only available if a script is installed and invoked through an entry point, not through the python command. Given that pex creates a self-contained Python environment, we're trying to understand if there's a way to directly invoke a script within a PEX without using the python command. Here's the configuration we're using to build the pex_binary:
Copy code
pex_binary(
    name="cli_binary",
    script="script",
    dependencies=[
        ":cli",
		...
    ],
)
And here's the associated python_distribution:
Copy code
python_distribution(
    name='cli',
    dependencies=["!//:root#cli"],
    provides=setup_py(
        name='cli',
        version='0.1.0',
    ),
    entry_points={
        "console_scripts": {
            "script": "cli.__main__:main"
        }
    },
)
• For reference: Click docs on shell completion
e
@bumpy-spring-43024 have you tried
execution_mode="venv"
for your
pex_binary
?: https://www.pantsbuild.org/docs/reference-pex_binary#codeexecution_modecode
This is a lazy suggestion AFK, but I'll try from the CLI with Pex in ~4 hours.
b
Thanks for getting back to me, I will check this tomorrow.
e
Yeah, venv mode does the trick. For example, just using Pex:
Copy code
jsirois@Gill-Windows:~/support/pants/JanBar $ pex hatch -c hatch -- new --cli example
example
├── src
│   └── example
│       ├── cli
│       │   └── __init__.py
│       ├── __about__.py
│       ├── __init__.py
│       └── __main__.py
├── tests
│   └── __init__.py
├── LICENSE.txt
├── README.md
└── pyproject.toml
jsirois@Gill-Windows:~/support/pants/JanBar $ pex example/ -c example --venv -o ~/bin/example
jsirois@Gill-Windows:~/support/pants/JanBar $ _EXAMPLE_COMPLETE=bash_source example
_example_completion() {
    local IFS=$'\n'
    local response

    response=$(env COMP_WORDS="${COMP_WORDS[*]}" COMP_CWORD=$COMP_CWORD _EXAMPLE_COMPLETE=bash_complete $1)

    for completion in $response; do
        IFS=',' read type value <<< "$completion"

        if [[ $type == 'dir' ]]; then
            COMPREPLY=()
            compopt -o dirnames
        elif [[ $type == 'file' ]]; then
            COMPREPLY=()
            compopt -o default
        elif [[ $type == 'plain' ]]; then
            COMPREPLY+=($value)
        fi
    done

    return 0
}

_example_completion_setup() {
    complete -o nosort -F _example_completion example
}

_example_completion_setup;
💯 1
b
Thanks a lot. I was only able to test this today, and it definitely pointed me in the right direction. Very cool to get a working example 👍