This is a note-to-self on setting up a 2020 13-inch MacBook Pro, largely for Python development. I imagine it will all be out-of-date by the time I set-up my next laptop but it’s possible it might be useful to someone in the meantime.
Applications
I don’t tend to use Homebrew Cask and suffer the indignity of either installing
them from the App Store or downloading .dmg
files and dragging them into
/Applications
.
From the App Store
There’s only a few of these that I use:
- Bear — my Bear notes are now my most valuable possession.
- Trello — by far my favourite workflow management app.
- Microsoft To Do — successor to Wunderlist.
- Slack
- Outline VPN client
Downloaded and dragged into /Applications
In rough order of usefulness:
- Alfred — install this Bear workflow and ensure it’s configured to search Chrome bookmarks.
- MacVim — install from Github to get the latest version.
- iTerm2
- Chrome
- 1Password (deliberately not from the App Store as such versions don’t support the QR code reader functionality)
- Spectacle
- Spotify
- Docker Desktop
- Postgres.app
- Zoom
- Dropbox
- Basecamp
- Vagrant
Homebrew formulae
Homebrew is best reserved for core system packages, where running the latest version is desirable. It’s less appropriate for project dependencies which require pinned versions — Docker is a better for that.
Start by installing Xcode’s command-line tools:
sudo xcode-select --install
then install Homebrew and a core set of formulae. The
following is taken from a setup_new_macbook.sh
script I use:
function install_homebrew_core_packages() {
local packages=(
bash
bash-completion
coreutils
ctags
fd
fzf
git
graphviz
htop
httpie
hub
hugo
imagemagick
jq
pgbadger
pv
rename
ripgrep
terminal_notifier
the_silver_searcher
)
brew install ${packages[@]}
}
plus some packages that require a separate tap
:
function install_homebrew_tap_packages() {
brew tap heroku/brew && brew install heroku
brew tap homebrew/cask-fonts
local fonts=(
font-inconsolata
font-clear-sans
font-source-code-pro
font-anonymous-pro
)
brew cask install ${fonts[@]}
}
Ensure your ~/.bash_profile
has shell completion enabled for Homebrew-installs
packages by following the
documented instructions.
MacOS configuration
It’s too dull to go through everything. Here are few notable changes:
Non-breaking spaces
Unbind ⌥ + SPACE from
inserting a non-breaking space by setting the contents of
~/Library/KeyBindings/DefaultKeyBinding.dict
to:
{
"~ " = ("insertText:", " ");
}
This avoids a common annoyance when editing headers in markdown files (eg in Bear).
System preferences
Here’s a configurure_system_preferences.sh
script I use:
#!/usr/bin/env bash
#
# Configure MacOS settings.
set -e
function configure_all() {
configure_keyboard
configure_screensaver
configure_screencapture
configure_touchpad
}
function configure_keyboard() {
# Set fast key repeat rate.
defaults write NSGlobalDomain KeyRepeat -int 2
defaults write NSGlobalDomain InitialKeyRepeat -int 15
}
function configure_screensaver() {
# Require password as soon as screen-saver or sleep mode starts.
defaults write com.apple.screensaver askForPassword -int 1
defaults write com.apple.screensaver askForPasswordDelay -int 0
}
function configure_screencapture() {
# Disable shadow effect in screen capture.
defaults write com.apple.screencapture disable-shadow -bool true
}
function configure_touchpad() {
defaults write com.apple.driver.AppleBluetoothMultitouch.trackpad Clicking -bool true
defaults -currentHost write NSGlobalDomain com.apple.mouse.tapBehavior -int 1
}
configure_all
Further reading
- How to set up a new Mac for development - A 90 minute video walking through setting up a MacBook Pro.
osx-for-hackers.sh
— A large shell script with a lot of configuration options. This is the Yosemite/El Capitan edition – not everything works in Catalina. It’s worth browsing though to see if anything takes your fancy.
Python
General principles:
-
Use
pyenv
to manage multiple versions of Python locally, and to stay out of the way of the system Python. -
Keep everything in virtualenvs.
-
Use
virtualenvwrapper
to provide convenience commands. Mainly as I like to switch to a project withworkon
. Indeed, I often create virtualenvs for non-Python projects just so I jump to them withworkon
and run some initialisation in thepostactivate
script (like changing to the project directory and setting the iTerm tab title). -
Use
pipx
to install command-line Python apps likeawscli
that I want available globally (i.e. can be run without activating a virtualenv first).
Python versions
Install pyenv
and pyenv-virtualenvwrapper
:
brew install pyenv pyenv-virtualenvwrapper
and ensure these libraries are initialised by adding:
if which pyenv > /dev/null 2>&1
then
# Pyenv (will add shims to front of $PATH)
eval "$(pyenv init -)"
# Ensure commands from virtualenvwrapper are available, no matter which
# Python version is active. This is equiv to sourcing virtualenvwrapper.sh
pyenv virtualenvwrapper
fi
to ~/.bash_profile
.
Install a modern Python as the global default:
pyenv install 3.8.3
pyenv global 3.8.3
plus any other Python versions that projects require.
Python projects
For each Python project, create a virtualenv by selecting the appropriate Python
version using pyenv
then using mkvirtualenv
:
cd $PATH_TO_PROJECT
pyenv local 3.7.7 # for example
mkvirtualenv $PROJECT_NAME
To avoid accidentally installing packages outside of a virtualenv, set:
# Always require a virtualenv to use pip
export PIP_REQUIRE_VIRTUALENV=true
in ~/.bash_profile
. If you do want to run pip
outside of a virtualenv, use
something like:
PIP_REQUIRE_VIRTUALENV=false pip list
Python command-line apps
Install pipx
with:
brew install pipx
and ensure ~/.local/bin
is on your $PATH
.
Install CLI apps:
pipx install awscli
Further reading
- My Python Development Environment, 2020 Edition by Jacob Kaplan-Moss (2019).