hjwp / Book-TDD-Web-Dev-Python

Book - TDD web dev with Python
https://www.obeythetestinggoat.com
Other
484 stars 175 forks source link

Makefile uses plain python instead of python3 which leads to command not found error #224

Closed paatre closed 5 months ago

paatre commented 5 months ago

I wanted to take a closer look into the repository for some possible contributions by cloning it to my local machine and followed README for setup.

But I noticed right away that make install can't be ran without errors:

$ make install
which uv && uv venv .venv || python -m venv .venv
/bin/bash: line 1: python: command not found
make: *** [Makefile:50: .venv/bin] Error 127

Shouldn't python -m venv .venv be python3 -m venv .venv? I do have python set as an alias for python3 in my .bashrc but it isn't used because the Bash used by make (SHELL := /bin/bash defined in Makefile) is a non-interactive shell.

hjwp commented 5 months ago

What OS still ships Python 2 as the default Python?

[edit] - sorry i realise that's a little rude, i don't mean to be, and i'm keen to support as many possilbe contributors as possible!

i think you might be able to get it working by doing source ~/.bashrc in your ~/.bash_profile ? i seem to remember that noninteractive shells only source one of those two...

paatre commented 5 months ago

Did not take that as rude so no worries!

The problem here lies on PEP 394. It has some great outlingings of the Python runtime distribution situation in 2011 when the PEP was created (especially Abstract and History of this PEP!), and the PEP and its recommendations are still active after 13 years! The most relevant part to this issue are these two bullet points:

  • If the python command is installed, it is expected to invoke either the same version of Python as the python3 command or as the python2 command.
  • Distributors may choose to set the behavior of the python command as follows:
    • python2,
    • python3,
    • not provide python command, allow python to be configurable by an end user or a system administrator.

Some distros provide a python command and some not. For example, Debian and Ubuntu only have python3 installed by default. Here are both distro's wiki pages on this issue: https://wiki.debian.org/Python and https://wiki.debian.org/Python. Here's a citation from the Ubuntu's wiki page because of its relation on the PEP 394:

/usr/bin/python will point to Python 3. No, this is not going to happen (unless PEP 394 advocates otherwise, which is doubtful for the foreseeable future).

To have a different example as well, here's Fedora's wiki page: https://fedoraproject.org/wiki/Changes/Python_means_Python3.

In package and command names, "Python" will mean "Python 3".

Users installing and running Python or Python packages without specifying a version will get Python 3.

Running python will run python3.

I'm on the latest Ubuntu, Ubuntu 23.10, and here's what apt show says:

$ apt show python
Package: python
State: not a real package (virtual)
N: Can't select candidate version from package python as it has no candidate
N: Can't select versions from package 'python' as it is purely virtual
N: No packages found

$ apt show python3
Package: python3
Version: 3.11.4-5
Priority: important
Section: python
Source: python3-defaults
Origin: Ubuntu
...

Then, let's get back to python3. Here's what PEP 394 states on it:

  • We expect Unix-like software distributions (including systems like macOS and Cygwin) to install the python2 command into the default path whenever a version of the Python 2 interpreter is installed, and the same for python3 and the Python 3 interpreter.

  • If the python command is installed, it is expected to invoke either the same version of Python as the python3 command or as the python2 command.

So, because python3 is always expected to be provided by Python runtime distributors, wouldn't it be more applicable to use python3 in the Makefile as well?

Then regarding Bash startup files, here's what Bash manual says:

Invoked non-interactively

When Bash is started non-interactively, to run a shell script, for example, it looks for the variable BASH_ENV in the environment, expands its value if it appears there, and uses the expanded value as the name of a file to read and execute. Bash behaves as if the following command were executed:

if [ -n "$BASH_ENV" ]; then . "$BASH_ENV"; fi

but the value of the PATH variable is not used to search for the filename.

As noted above, if a non-interactive shell is invoked with the --login option, Bash attempts to read and execute commands from the login shell startup files.

So yes, I could use BASH_ENV to have my Bash aliases applied but it feels a bit counterintuitive if Makefile could just use the python3 command. Also, people not having python command provided by their distro and having to use BASH_ENV may lead to them having different experiences with the Makefile regarding on the differences with their Bash files.

hjwp commented 5 months ago

hmmm. well i think python3 will work ok on linuxes and also on macos, but fail on windows... but then again most stuff will fail on windows so.

hjwp commented 5 months ago

lmk if that fix looks ok to you!

hjwp commented 5 months ago

thanks for the extremely thorough reply btw! i learned plenty. really appreciate that.

paatre commented 5 months ago

thanks for the extremely thorough reply btw! i learned plenty. really appreciate that.

Really nice to hear that the reply was helpful for you. Thank you for your comment, Harry! Made my day. 😊

lmk if that fix looks ok to you!

It looks good!

hmmm. well i think python3 will work ok on linuxes and also on macos, but fail on windows... but then again most stuff will fail on windows so.

Yeah, sure, you're not wrong here. Also, README seems to already nudge towards WSL2 on Windows.

Then again, I do think it would be great to think of a way to have a support for OS-independant Makefile. There are multiple sources that seem to indicate that the use of an OS environment variable could be used [^1][^2][^3]. But some sources (even on some of the previous ones as well) do mention a uname command that may be used as well but I'm not sure if it's always included in Windows systems [^4][^5].

I don't even have a Windows machine myself ready at the moment to test these (even though I could try my wife's Windows laptop). I may create a VM for testing this at some point, haven't done created one before so it could be fun.

[^1]: Stack Overflow: OS detecting makefile [^2]: GitHub Gist: Detect operating system in Makefile. [^3]: Stack Overflow: Platform-dependent Makefile [^4]: O'Reilly: Managing Projects with GNU Make, 3rd Edition by Robert Mecklenburg. Chapter 7. Portable Makefiles [^5]: Superuser: How to detect windows OS in shell script

hjwp commented 5 months ago

I do think it would be great to think of a way to have a support for OS-independant Makefile

haha i'm not sure this repo has enough contributors to really be worth the effort! it would be purely out of intellectual curiosity...