Reputation: 173
I'm trying to distribute a shell script along with a Python package. Ideally, the shell script is installed when I run pip install my_package
. I read from this SO that, my expected behavior is exactly what the scripts
keyword of setuptools.setup
provides. E.g. the script my_script
will be installed with the following setup.py
script:
setup(
...
scripts=['my_script'],
...
)
However, I cannot use the above method for two reasons:
pyproject.toml
, without setup.py
. Although pyproject.toml
has provided a [project.scripts]
table, as explained in the setuptools official doc, the scripts can only be python functions instead of shell scripts.For completeness, in my case, the shell script reads git
status and sets environment variables, which will be read from within my python project. The shell script and my python project are bonded so tightly that I would rather not split them into two projects.
I have also tried to use a python function to execute the shell script, e.g.
[project.scripts]
my_script = 'my_project:my_func'
def my_func():
subprocess.run(...)
The problem with this solution is that every time I run my_script
, my_project
is loaded and the loading process is really slow.
Upvotes: 17
Views: 5128
Reputation: 17332
Maybe a link in the comments leads to this information already. Anyway, I think it is worth posting that scripts = [...]
in setup.py
can be written in pyproject.toml
as:
[tool.setuptools]
script-files = ["scripts/myscript1", "scripts/myscript2"]
However, this feature is deprecated (see the UPDATE below). I hope the authors of the packaging tools will recognize the problem with shell scripts and deal with it.
UPDATE - I checked the docs recently (January 2024) and now it is tagged discouraged (was deprecated). IMO this is good news, because the chance it is going to be removed is now lower.
Link: setuptools docs
Upvotes: 18
Reputation: 107
I'm not exactly sure it will work for you case, but I solved this by creating a "shim" setup.py
file (it has an added benefit of being able to install your project in edit mode).
It usually just calls setup()
, but it was possible to pass the scripts
argument:
"""Shim setup file to allow for editable install."""
from setuptools import setup
if __name__ == "__main__":
setup(scripts=["myscript"])
Everything else was loaded from pyproject.toml
.
Upvotes: 2