Add entry points to setup.py
This PR adds the entry_points field to setup.py to allow an easy access to the xrt GUI via a command line, i.e. by simple typing of xrt after the installation one will get the xrtQook GUI running.
Maybe the scripts field won't be needed anymore: https://github.com/kklmn/xrt/blob/75b884c0cba7e1aac15b30f2d0d803597328a208/setup.py#L206
@kklmn, @yxrmz, I saw a new release 1.4.0. Would you be able to consider my contribution to be included in a future release? Is there any blocker here you'd like to address?
what are the main points?
why entry_points should be better?
With entry_points one does not have to know the path to the scripts, and typing xrt would be enough to start the script. In the present approach a user will have to identify where the library is installed, and point to that place, e.g., <...>/lib/python3.x/site-packages/xrt/gui/xrtQookStart.py.
-
We have
scriptskw in setup.py that copies xrtQookStart.py to Scripts location. It is normally in your PATH, so you don't need the full path, justxrtQookStart.py. And this is not much longer thanxrt. -
Running setup.py is not required to have a working installation of xrt. You may have it at any location and in several versions. This is explained in the docs. Having
entry_pointswould need extra documentation lines (explaining the usage ofxrt) but what is worse, the docs would need branching: "if you use setup.py do this, if you don't use setup.py do that"...
No, I don't like it.
Thanks, I did not use scripts in the past, and it's reasonable the script is accessible via a directory in $PATH. However, when I use it directly via xrtQookStart.py, I get this error:
13:54 $ xrtQookStart.py
/Users/mrakitin/miniconda3/envs/xrt/bin/xrtQookStart.py: line 2: This script launches xrtQook.: command not found
/Users/mrakitin/miniconda3/envs/xrt/bin/xrtQookStart.py: line 3: __author__: command not found
/Users/mrakitin/miniconda3/envs/xrt/bin/xrtQookStart.py: line 4: __date__: command not found
/Users/mrakitin/miniconda3/envs/xrt/bin/xrtQookStart.py: line 6: import: command not found
/Users/mrakitin/miniconda3/envs/xrt/bin/xrtQookStart.py: line 7: import: command not found
/Users/mrakitin/miniconda3/envs/xrt/bin/xrtQookStart.py: line 8: syntax error near unexpected token `os.path.join'
/Users/mrakitin/miniconda3/envs/xrt/bin/xrtQookStart.py: line 8: `sys.path.append(os.path.join('..', '..'))'
While it works successfully with xrt from entry points:

OK, the problem is that the shebang is not present in your scripts. That's why directly calling xrtQookStart.py was treated as a bash script, not the Python code.
Adding #!/usr/bin/env python helped to solve the issue. However, one has to make sure this shebang is always there for scripts while entry points will take care of it for you. Another advantage is that it can handle a Python interpreter from conda (and probably venv), as it automatically updates the shebang line to the script in bin as:
$ head -1 `which xrt`
#!/Users/mrakitin/miniconda3/envs/xrt/bin/python
a5212e5 addresses the issue with the missing shebang strings with the interpreter. https://en.wikipedia.org/wiki/Shebang_(Unix) has it as an example.
I found https://python-packaging.readthedocs.io/en/latest/command-line-scripts.html#the-scripts-keyword-argument useful. From that tutorial, the scripts kwarg is designed to support general scripts, while entry_points are for Python functions. As xrtQookStart.py is a Python code, it is natural to use entry points. They should generate platform-specific executables more consistently on Win/Linux/Mac. Just something to consider before rejecting this PR 😉
while entry_points are for Python functions
I think this speaks against using entry_points as we do not export functions but rather scripts as full modules.
As xrtQookStart.py is a Python code, it is natural to use entry points.
I hope that at least you can explain this logical connection to yourself. 😉
Anyways, this is not the main point but rather my item "2" above.
while entry_points are for Python functions
I think this speaks against using
entry_pointsas we do not export functions but rather scripts as full modules.
Right, but if you check my proposed changes, the 3 line in https://github.com/kklmn/xrt/pull/42/commits/7523959e3f50edc15246b85a9c6048dd46ed87d3 wrap the code into the main function, and it's not an obstacle anymore. My point was that if one wants to add .sh or other language scripts, then the scripts approach is the only possible solution, while with Python code (that you own and can control), there are 2 ways, and the second entry_points approach is more future-proof. I invite you to read this answer and below on SO: https://stackoverflow.com/a/28119736. The important bit is cross-platform support. How cross-platform is your approach? I installed the master branch of xrt on MacOS, Linux, and Windows just now, and when I type xrtQookStart.py, it fails on both Mac and Linux as it's missing the shebang I pointed to and fixed via https://github.com/kklmn/xrt/pull/42/commits/a5212e50753c455a2b9cc4cba1af01701ef0548f. However on Windows, when I run the same command, it opens the script in a Notepad, so the behavior is ambiguous. With entry_points Python generates proper xrt.exe file that can be executed with no issues and guesses.
I just would like to point you to my efforts in nsls2forge conda channel (the package is now ported to conda-forge):
- this is a feedstock repo for packaging, where I apply the patch that adds entry points: https://github.com/nsls-ii-forge/xrt-feedstock
- the resulting files for each platform can be found at https://anaconda.org/nsls2forge/xrt/files. I encourage you to download a Windows archive, and see the content. You'd notice that:
...
├── Scripts
│ ├── __pycache__
│ │ └── xrtQookStart.cpython-37.pyc
│ ├── xrt.exe
│ ├── xrtQookStart.py
│ ├── xrtQookStart.pyw
│ └── xrt-script.py
...
This is a proper executable:
$ file Scripts/xrt.exe
Scripts/xrt.exe: PE32+ executable (console) x86-64 (stripped to external PDB), for MS Windows
For Linux/Mac xrt is an executable script with the actual Python executable path in the shebang.
As xrtQookStart.py is a Python code, it is natural to use entry points.
I hope that at least you can explain this logical connection to yourself. wink
The logical connection is very simple - make use of the existing tooling for a cross-platform support (again, Python code, fully under your control to tune it to use the tools).
Anyways, this is not the main point but rather my item "2" above.
I don't think either scripts or entry_points are involved in that use case as no installation is happening/no setup.py is involved.
Happy 3rd anniversary to this PR! 🎉 @kklmn, @yxrmz, did you make a decision on whether it will be merged or not? Thank you for your consideration.