I'm packaging some python packages using a well known third party packaging system, and I'm encountering an issue with the way entry points are created.
When I install an entry point on my machine, the entry point will contain a shebang pointed at whatever python interpreter, like so:
in /home/me/development/test/setup.py
from setuptools import setup
setup(
entry_points={
"console_scripts": [
'some-entry-point = test:main',
]
}
)
in /home/me/.virtualenvs/test/bin/some-entry-point:
#!/home/me/.virtualenvs/test/bin/python
# EASY-INSTALL-ENTRY-SCRIPT: 'test==1.0.0','console_scripts','some-entry-point'
__requires__ = 'test==1.0.0'
import sys
from pkg_resources import load_entry_point
sys.exit(
load_entry_point('test==1.0.0', 'console_scripts', 'some-entry-point')()
)
As you can see, the entry point boilerplate contains a hard-coded path to the python interpreter that's in the virtual environment that I'm using to create my third party package.
Installing this entry point using my third-party packaging system results in the entry point being installed on the machine. However, with this hard-coded reference to a python interpreter which doesn't exist on the target machine, the user must run python /path/to/some-entry-point
.
The shebang makes this pretty unportable. (which isn't a design goal of virtualenv for sure; but I just need to MAKE it a little more portable here.)
I'd rather not resort to crazed find/xargs/sed commands. (Although that's my fallback.)
Is there some way that I can change the interpreter path after the shebang using setuptools
flags or configs?
Entry points are a type of metadata that can be exposed by packages on installation. They are a very useful feature of the Python ecosystem, and come specially handy in two scenarios: 1. The package would like to provide commands to be run at the terminal. This functionality is known as console scripts.
The console_scripts Entry Point Setuptools allows modules to register entrypoints which other packages can hook into to provide certain functionality. It also provides a few itself, including the console_scripts entry point.
exit( load_entry_point('rss2sms==0.0.1', 'console_scripts', 'rss2sms')() ) This executable is just a simple python module which, when we call it, uses the pkg_resources library to look up what python module our setup.py says we should call.
In NetSuite terminology, an "Entry Point Script" is the module you write that will be assigned as the source file on a Script record. If your module requires an @NScriptType tag, then it is most certainly an Entry Point Script.
You can customize the console_scripts' shebang line by setting 'sys.executable' (learned this from a debian bug report). That is to say...
sys.executable = '/bin/custom_python'
setup(
entry_points={
'console_scripts': [
... etc...
]
}
)
Better though would be to include the 'execute' argument when building...
setup(
entry_points={
'console_scripts': [
... etc...
]
},
options={
'build_scripts': {
'executable': '/bin/custom_python',
},
}
)
For future reference for someone who wants to do this at runtime without modifying the setup.py
, it's possible to pass the interpreter path to setup.py build
via pip
with:
$ ./venv/bin/pip install --global-option=build \
--global-option='--executable=/bin/custom_python' .
...
$ head -1 ./venv/bin/some-entry-point
#!/bin/custom_python
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With