pyenv is a very handy tool for working with multiple versions of Python, including versions that may not natively be available for your system. It functions like a package manager, handling the compilation of the desired versions of Python, and lets you easily switch between them at will.

Installing pyenv

Installing pyenv is easy. On macOS, you'll need Homebrew, so install that first. On Linux, you will need to install some development packages so that the appropriate native modules can be compiled.

<aside> 🛑

STOP: Apple M1 users, take note!

If you're running on Apple's M1 (ARM) architecture, run arch in your terminal and make sure it says arm64. If you're running in some shell that's using Rosetta's Intel compatibility, it will say i386 or x86_64. This can result in Python problems down the road *unless you're explicitly trying to test an Intel configuration!

Also,* if you've previously done a brew coreutils and put the gnubin path in $PATH, you must remove the uname symlink from that directory, or remove gnubin from your $PATH. It will return results that will break Python installation. (Some versions of Python in pyenv work around this, but they’re planning to move away from the workarounds.)

(Updated December 19, 2021)

</aside>

# On macOS (Intel):
$ brew install pyenv

# On macOS (M1), you will need to have the latest versions in Git.
# This is due to patches that (as of this writing — December 19, 2021),
# are not in brew's version.
$ curl <https://pyenv.run> | bash

# On Linux -- see <https://github.com/pyenv/pyenv-installer>
$ apt-get install libbz2-dev libreadline-dev libsqlite3-dev
$ curl <https://pyenv.run> | bash

Follow the instructions and add the necessary environment variables to your ~/.bashrc or equivalent for your shell.

Installing Python versions

Once installed, you'll want to install the desired versions of Python. This is also easy, but we're going to show some instructions that work around issues with old versions on macOS.

# If you're on macOS:
#
# * We'll first install a newer sqlite to avoid a crash in the
#   old system-provided version.
#
# * We'll also enable frameworks and work around some flags that
#   can break install.
$ brew install sqlite
$ export BREW_PREFIX=$(brew --prefix)
$ export MAKEFLAGS=""
$ export PYTHON_CONFIGURE_OPTS="LD_RUN_PATH=$BREW_PREFIX/opt/sqlite/lib LDFLAGS=-L$BREW_PREFIX/opt/sqlite/lib CPPFLAGS=-I$BREW_PREFIX/opt/include --enable-framework"

# Now install however many versions you need.
#
# ===> Run `pyenv install -l` to see what's available. <===
#
# NOTE: You'll want the latest .Z for each Python X.Y release needed by the
#       versions of Review Board you're working with! Don't just copy these!
$ pyenv install <version>  # e.g., 2.7.18
$ pyenv install <version>  #       3.9.5
...

Here are the versions being used by Review Board today: