GeistHaus
log in · sign up

https://feeds.hackercodex.com/feeds/main

atom
13 posts
Polling state
Status active
Last polled May 19, 2026 01:50 UTC
Next poll May 20, 2026 01:14 UTC
Poll interval 86400s
ETag "dc7bk0q56n7k3djb-gzip"
Last-Modified Wed, 20 Aug 2025 14:19:32 GMT

Posts

Run a local LLM via Llama.cpp
guidellm

Run a local LLM via Llama.cpp and Open WebUI

Show full content

This guide demonstrates how to install and run a large language model (LLM) on your local workstation via Llama.cpp and, optionally, Open WebUI.

Choose a Model

There are many excellent models to choose from, but ultimately the optimal choice depends on your target use case as well your available system resources.

For text generation — as opposed to image/video/voice — Hugging Face offers a fairly comprehensive list of popular models.

For the purposes of this guide, we are going to use DeepSeek R1 0528 8B, a model with 8 billion parameters that when downloaded needs about five gigabytes of disk space.

Install Llama.cpp

As noted in the relevant installation documentation, Llama.cpp can be installed on Linux and MacOS via the Homebrew package manager:

brew install llama.cpp

Alternatively, you can download a pre-built binary from the releases page, or if you prefer, build from source.

Run Llama.cpp Server

Once Llama.cpp is installed, we can run its built-in server on any arbitrary port except for 8080, which we will reserve for Open WebUI. Upon first invocation, the Llama.cpp server will download and run the specified model:

llama-server --port 8888 -hf unsloth/DeepSeek-R1-0528-Qwen3-8B-GGUF:Q4_K_XL

The Llama.cpp server should now be running on the specified port. Visit http://localhost:8888 in your browser to load the web interface and start submitting prompts.

Open WebUI (optional)

While the web interface provided by llama-server is great for accessing models managed by Llama.cpp, Open WebUI is a web front-end that makes it easy to access non-Llama.cpp-managed models as well as remote LLMs. To install it, I suggest using Pipx (in a separate terminal tab):

pipx install open-webui

If you prefer uv, the corresponding installation command would be:

uv tool install open-webui

Start Open WebUI:

open-webui serve

Open your browser and visit: http://localhost:8080

Tap “Get Started”, and enter any data you want for for name, email, and password. This data is used for your local account, so you can enter arbitrary dummy data if you prefer.

(Note: Open WebUI claims to not make any external connections, but on startup I noticed that it connected to HuggingFace, which personally I do not mind since that is where many models are located. Upon account creation, however, Open WebUI also tried to connect to OpenAI and GitHub, both of which I blocked at the network level. I imagine these are innocent and useful to use this tool, but I blocked them since I do not need connections to those services.)

Open WebUI Configuration

User avatar icon > Admin Panel > Connections > (disable OpenAPI and Ollama APIs)

User avatar icon > Settings > Connections > + (Add Connection)

URL: http://127.0.0.1:8888/v1
Key: (leave blank)

Tap the Save button and close the Settings modal.

Select a model from the top navigation if not already selected. Select Temporary Chat if you want to test or otherwise avoid queries/responses from being logged.

Tap on the field labeled with “How can I help you today?” and enter your prompt to query the LLM.

For more information about using Open WebUI with Llama.cpp, refer to the related documentation.

Summary

Now you can run LLMs on your own workstation. If you have any questions, comments, or suggestions, please reach out via the Fediverse!

tag:hackercodex.com,2025-06-17:/guide/local-llm-llama-cpp/
Convert reStructuredText to Markdown
guidemarkdownpelican

Convert reStructuredText to Markdown, optionally including front-matter metadata.

Show full content

This guide demonstrates how to convert reStructuredText (reST) files to Markdown, optionally including front-matter metadata in a Pelican context.

Tools Used in this Guide

The following tools (tap on them for the links) were used in this guide:

  • pandoc: To convert from reST to Markdown
  • fd: To recursively find files on which to execute commands
  • sd: To recursively find and replace text strings
  • trash | macos-trash (optional): To safely, non-destructively remove files
  • Pelican (optional): To test converted Markdown files via Pelican
  • Related resource, just for reference: rst_to_md.sh
Convert reST Files to Markdown

Use pelican-quickstart to create a new project called testsite and copy the Pelican web site’s reST content into the new project:

cd ~/Desktop/
pelican quickstart
cd ~/Desktop/testsite
cp -r ~/projects/pelican-website/content/news/ content
cd ~/Desktop/testsite/content

Recursively find and convert all .rst files to Markdown:

fd -e rst --exec pandoc {} -f rst -t markdown -o {.}.md

Trash the .rst files (replace trash with rm if trash is unavailable, or with git rm if in a Git repository):

fd -e rst --exec trash

Try converting the first # […] header to a title: […] metadata field in a single file:

sd -n 1 '^# (.*)$' 'title: $1' pelican-4.10.md

Try cleaning up the misshapen remaining metadata headers in a single file:

sd '\n(.*)\n\n:   (.*)\n' '$1: $2\n' pelican-4.10.md

Inspect the modified file. Assuming the above has done everything necessary, it is time to perform those operations recursively on all Markdown files.

Recursively convert the first # […] header to title: […] metadata:

fd -e md --exec sd -n 1 '^# (.*)$' 'title: $1'

Recursively clean up the misshapen remaining metadata headers:

fd -e md --exec sd '\n(.*)\n\n:   (.*)\n' '$1: $2\n'

Use Pelican to test building the converted Markdown files:

cd ~/Desktop/testsite
pelican build

→ Done: Processed 23 articles, 0 drafts, 0 hidden articles, 0 pages, 0 hidden pages and 0 draft pages in 0.29 seconds.

In this case, the conversion was successful ✨

Did this work for you? Reach out and let me know!

tag:hackercodex.com,2024-11-05:/guide/convert-restructuredtext-to-markdown/
How to Clean-Install macOS
guidemacgeekery

Clean-installing macOS can make your Mac faster and more reliable by clearing out outdated/corrupted files. Learn how to go “scorched earth” and clear out the bit-rot on your Mac.

Show full content

Clean-installing macOS can make your Mac faster and more reliable by clearing out the operating system cobwebs. Sometimes referred to as “bit-rot,” various files can become outdated or corrupted, hobbling your computer’s speed and sometimes yielding crashes. After using a computer for a few years, with several in-place upgrades performed over that time span, there inevitably comes a time when I decide to erase the drive and cleanly install the latest version of the Mac operating system. I call this going “scorched earth.”

For clean installations, I prefer to create bootable installers on USB drives. This isn’t strictly necessary, as Apple provides alternative methods that don’t require creating bootable installers. Here’s why I do:

  1. they can be used to install on more than one Mac
  2. because I’m old-school
What You’ll Need
  • the administrative password for your Mac
  • 8GB or larger USB drive (flash/thumb drive is fine — will be completely erased)
Back Up Your Mac

Before you do anything, back up your Mac. Right now.

By ensuring that you have backups of all the data on your internal drive, you will then be able to move back over certain applications, documents, and other files that you actually want to keep — while leaving the unnecessary detritus behind.

Please note that this latter process — copying back over the data/files you want to keep — is beyond the scope of this article. So if you don’t feel totally confident that you know how to do that, please do not continue with the rest of this guide. Instead, find someone who can help guide you through the process.


showgoods();

Download macOS
  1. Tap the following link to go to App Store, then tap the Download button: macOS Mojave

  2. Once the macOS download finishes, the installer will automatically be launched. We aren’t ready for that yet, so go to the Install macOS Mojave menu and select Quit Install macOS to quit the Installer app without performing the installation.

Create Bootable Installer
  1. Insert 8GB or larger USB flash/thumb drive. Rename to: MacInstaller
  2. Launch Disk Utility (Finder > Applications > Utilities > Disk Utility)
  3. From left-hand sidebar, look under External and choose MacInstaller
  4. Tap on the Erase tab at the top of the window.
  5. Select Mac OS Extended (Journaled) from the format list and then tap Erase.
  6. When done, tap Done and quit Disk Utility.
  7. Launch Terminal (Finder > Applications > Utilities > Terminal)
  8. Enter the following text and then hit Return: sudo /Applications/Install\ macOS\ Mojave.app/Contents/Resources/createinstallmedia --volume /Volumes/MacInstaller
  9. Enter your administrator account password and hit Return. This is the password you use to make changes on your Mac or log in. No text will appear in Terminal when you enter the password. When prompted, enter Y to confirm that the drive will be erased and hit Return again.

The last step will take a long time. When finished, it will report: Done.

(If you need more detail regarding this process, refer to Apple’s documentation: How to create a bootable installer for macOS)

Clean Install macOS
  1. Leaving your installer drive connected via USB, restart your Mac.
  2. The screen will turn off for a moment. Before the screen lights up again, hold down the Option key until you see a list of drive icons.
  3. Use arrow keys to select the install macOS Mojave icon and hit Return.
  4. Choose Disk Utility and then Continue.
  5. In the left-hand sidebar, select your internal drive and then tap the Erase button in the top toolbar.
  6. Ensure the Format drop-down menu is set to: OS X Extended (Journaled), and then tap Erase.
  7. Erase step should complete quickly. Tap Done button and quit Disk Utility.
  8. Select Install macOS and then tap the Continue button.
  9. Scroll through license agreement and tap the Agree button.
  10. Select your internal drive and tap the Install button.
  11. Ignore the wildly inaccurate time estimate and go do something else. You’ll know the process is done when you see a macOS setup screen.
  12. After a long wait, you will see a welcome screen asking you to choose a country/language. Make your selection and tap the Continue button.

Continue going through the initial Mac setup process. Once login completes, eject the Install macOS Mojave USB drive.


showgoods();

Migrating Your Data

Re-installing macOS from scratch means that none of your data has come along for the ride, with the possible exception of contacts, calendar events, and any other information that you’ve chosen to synchronize via iCloud. There are two primary choices for migrating your data: manual and automatic.

Manually Copy Data

If you have reason to believe your old macOS installation had problems that would be carried over to your new system if you performed an automatic migration, you can attempt to manually copy over your documents and other data. This is rarely necessary, requires intimate knowledge of macOS and its data locations, and will almost always result in something not getting migrated that you actually wanted to be migrated. Therefore, this is a last resort and should only be attempted if you really know what you’re doing.

Automatic Migration via Migration Assistant

Most people will be better served by the Migration Assistant application, which automatically migrates your data from another Mac or backup. You made a Time Machine backup just before re-installing macOS, right? Good. The first time you boot into your new macOS installation, during the setup process you may be asked whether you want to transfer information to it. That is a good time to connect your Time Machine backup drive to your computer, select the “Time Machine backup” option, and select your Time Machine backup drive as the migration source. For more details regarding this process, refer to Apple’s Migration Assistant documentation.

Final Thoughts

Clean-installing macOS is no panacea, but I (and some of my friends and family) have been very pleased with the results. It can make an old Mac feel new again, which sometimes can be well worth the hassle of setting everything up again from scratch. (And yes, that is definitely a hassle.)

Any thoughts on this topic? Suggestions for improvement? Please reach out and let me know


showgoods();

tag:hackercodex.com,2017-10-24:/guide/macos-clean-install/
Mac Backup Strategy
guidemacgeekery

Implement a Mac backup strategy, including local backups via SuperDuper and off-site backups via Arq, in this step-by-step tutorial to guard against irreversible data loss.

Show full content

I sometimes ask friends and family members about their backup strategies, a question usually met by sheepish looks and mumbled confessions of neglect. I tell them not to feel bad; the only reason I ask is because I don’t want them to make the same mistakes that I’ve made in the past.

This conversation is usually followed by me setting up an automated backup system for them. That doesn’t scale very well, so I have written this guide so folks can set it up on their own.

Formulate a Backup Strategy

The first step is to come up with a backup strategy. For me, that means a minimum of:

  • local bootable clone
  • local Time Machine backup
  • off-site backup

Having a bootable clone means that if your primary drive fails or gets corrupted, you can boot into your clone and be back up and running immediately, without any down-time.

Time Machine backups are not bootable, but they have something that the clone does not: versioning. If you delete an important file by accident and don’t immediately realize it, and your drive is replicated to your clone, then that important file will also be deleted from your clone. With Time Machine, however, you can go back in time and restore that deleted file.

The purpose of the off-site backup is geographical redundancy. If your home is burglarized or destroyed by fire, you could lose your computer and all your backups, with the important data within lost forever. That’s why off-site backups are an important pillar of any backup strategy.

Now that we delineated a backup strategy, let’s implement it.

What You’ll Need
  • the administrative password for your Mac
  • external drive at least as twice large as internal drive (this external drive will be completely erased)
  • SuperDuper (optional but recommended)
  • Arq
  • Backblaze B2 account


showgoods();

External Drive Partitioning

If you have one external drive at least as large as your internal drive, and you have another, second external drive that’s at least 1.5 times as large as your internal drive, then you can skip this section. Otherwise, you will need to partition a single external drive that is at least twice as large as your internal drive. In either case, this tutorial assumes all these drives do not have any valuable data on them, as they will be fully erased in order to store the backups.

macOS performs best when you leave at least ~20% of your internal drive free, as it is often used for virtual memory and other OS-level functions. Ergo, the following calculations are based on the assumption that the primary internal drive always has at least 20% of its capacity as free, unallocated space.

  1. Clone partition size = at least as large as internal drive capacity
  2. Time Machine partition size = multiply Clone partition size by 1.5

Example:

If you have a 500 GB internal drive, the above formula yields the following minimum partition size allocations:

  • Clone: 500 GB
  • Time Machine: 750 GB

With your external drive connected to your Mac and powered on, use the Finder to launch Disk Utility, which is in Applications > Utilities. Select your external drive from the list at left and then tap the Partition button in the top-hand toolbar. If the button is grayed out, make sure you have selected the drive and not the indented volume shown beneath the drive in the list.

Use the pie chart, plus sign icon, and other controls to create the two partitions (Clone and Time Machine), ensuring the capacities are calculated as noted above. Once everything looks right, and you are absolutely certain you do not have any data that will be lost, proceed by selecting the Apply button.

Partitioning should be a fairly quick process. When done, quit Disk Utility and proceed to setting up Time Machine.

Local Backups Time Machine

Go to Apple Menu > System Preferences… > Time Machine and tap the Select Backup Disk… button. Choose the Time Machine volume from the list and then tap the Use Disk button.

That’s it. From now on, as long as your external drive is connected, Time Machine will automatically back up your internal drive every hour.

Clone Primary Drive

You can clone your drive via several methods, two of which are presented here. That said, I highly recommend you choose the first one, SuperDuper. Unlike the other method, SuperDuper can be set to clone on a consistent schedule, along with many other benefits. The developer works incredibly hard to make SuperDuper the best cloning product on the market; it is well worth the US$27.95 cost.

Recommended Method: Clone via SuperDuper
  1. Connect your external drive and rename it to: Clone

  2. Launch SuperDuper. Choose drives from the drop-down menus such that you see something like: “Copy (name of your internal drive) to Clone using Backup - all files”

  3. Making sure you are okay with your external drive being fully erased, tap the Copy Now button.

  4. Cloning will take a long time. When done, tap the OK button.

  5. Choose the Options button. From the During Copy drop-down menu, choose the item that starts with Smart Update… and then tap OK.

  6. Tap the Schedule button, choose a clone backup schedule that makes sense to you, and tap the OK button.

  7. Use Finder to locate your Clone external drive. Drag it to the Trash icon and let go to unmount it. Disconnect the USB cable from your computer.

Alternate Method: Clone via Disk Utility

This method is more complicated than using SuperDuper and requires booting into your internal drive’s recovery partition.

  1. Restart your Mac and immediately hold both Command and R keys until the Apple logo appears.
  2. When presented with a list of options, choose Disk Utility and then Continue.
  3. In the left-hand sidebar, select the Clone drive.
  4. From Disk Utility’s Edit menu, select Restore.
  5. From the sheet that appears, look for a drop-down menu next to “Restore from” and select your internal drive as the source.
  6. Tap the Restore button to begin cloning your internal drive to the external “Clone” drive.

Once the process is complete, tap Done to close the Restore sheet.

Stay Connected

One very important consideration to highlight is that both the Time Machine and SuperDuper-based backups can only occur when your computer is connected to the powered-on external drive(s). So if you don’t want external drive(s) connected and powered on all the time, you must figure out a way to remember to connect them periodically and let the backup processes run their course. Otherwise, all of this is for naught.


showgoods();

Off-Site Backups Choosing an Off-Site Storage Provider

I chose BackBlaze’s “B2” cloud storage for the following reasons:

  • no minimum cost: only pay when data is stored/transferred
  • monthly storage cost is among the lowest at $US0.005/GB/month
  • data restoration cost seems reasonable and doesn’t feel punitive

If you are already paying for Dropbox, Google Drive, or another cloud drive product, or if you don’t have much data to back up and can get by with a free plan, then you might find that to be a good option. I don’t like the minimum cost “floor”, plus per-gigabyte overage model, associated with these kinds of products. Backing up 500 GB, for example, costs only $2.50 on B2 but $5 per month via cloud drive services.

But that’s just my suggestion. Feel free to read more about this in Arq’s section on Choosing a Storage Provider.

Install and Configure Arq
  1. Purchase, download, and install Arq. Launch Arq and choose what to back up from Backups menu > Add (Home) Folder to Backups…
  2. Choose B2 when prompted.
  3. Log into B2.
  4. When prompted, create and name a new bucket.
  5. Once provider has been set up, enter Arq license key.
  6. Add home folder (or other desired starting point); enter long passphrase when prompted and store in your password manager
  7. Edit backup selections to exclude any large files/folders that you don’t care about losing, if any (example: huge game files that you could easily re-install)

Once you tap the OK button confirm your backup selections, you should be all set. Arq will automatically encrypt and back up your data to B2’s off-site storage facility.

Final Thoughts

As someone who is no stranger to data loss, I know first-hand how painful it can be. While there is a small financial cost to implementing a backup strategy like this one, and it would be nice if it were a little easier to set up, the effort is 100% worth the peace of mind. Once it’s configured, this system hums along in the background and silently prevents the loss of priceless family photos, home videos, and other data you simply cannot affort to lose.


showgoods();

tag:hackercodex.com,2017-10-23:/guide/mac-backup-strategy/
Vim Search Across Multiple Files in Project
guidevim

Searching within Vim across all files in the current project is more cumbersome than, say, TextMate’s Find in Project… feature. With just a few configuration changes, however, you can significantly level-up Vim’s searching capability.

Show full content

I frequently find myself needing to search for a string across all files in the current project. Before I switched to Vim, I would use TextMate’s Find in Project… feature to do this, which is highly efficient. After switching to Vim, however, for years I found myself without an equally effective solution and often capitulated by launching TextMate when I needed to search across multiple files. I would find the relevant file(s), open in Vim, and then continue editing there — clearly not an ideal solution.

Before you shout, “Why don’t you just :grep -R your-search-term .?” … Well, I tried that, but I didn’t find the output to be very useful. So I finally decided to do something about it and devised a solution that works well for me.

The first step is deciding what “engine” you want to power your searches. My order of preference is:

Once you have at least one of the above search tools installed, the next step is to install the ack.vim plugin via your preferred Vim plugin installation method.

To tell ack.vim to use my order of preference above, put the following in your .vimrc:

" Prefer rg > ag > ack
if executable('rg')
    let g:ackprg = 'rg -S --no-heading --vimgrep'
elseif executable('ag')
    let g:ackprg = 'ag --vimgrep'
endif

To begin searching, :cd to the desired directory and invoke ack.vim to search across all the files in that directory:

:cd ~/projects/yourproject
:Ack your-search-term


showgoods();

If you’d rather not have to :cd every time to set the search scope, install the Rooter Vim plugin to automatically set the working directory to the current project root.

I prefer to type a single keystroke to begin searching. The following Vim configuration aliases the backslash key to :Ack:

" Backslash invokes ack.vim
nnoremap \ :Ack<SPACE>

Search results will be presented in a location list, with the first result shown in the current buffer. You can tap the Return key to select that first result and dismiss the location list window, or you can use the usual movement keys (or search commands) to highlight other items in the list. Once you have highlighted the desired result, there are a number of keys you can use to open that file in a new tab or split.

Recursive Search & Replace

I haven’t found a great way to do recursive search and replace operations within Vim, so I currently use fd and sd for this purpose. For example, I recently wanted to replace a bunch of single-quotation marks to double-quotation marks, changing all occurrences of:

{% include 'path/to/django/templates/some-template.html' %}

… to:

{% include "path/to/django/templates/some-template.html" %}

I restricted the list of files to those with .html extensions and then used a regular-expression capture group to effect the changes:

sd "include '(.*)'" 'include "$1"' $(fd -e html)
Have a better solution?

I’m curious how other folks are searching across multiple files from within Vim, so please let me know how you handle this use case.

If you found this article to be useful, please follow me on Twitter and be sure to check out Fortressa!


showgoods();

tag:hackercodex.com,2016-10-04:/guide/vim-search-find-in-project/
Tacklebox for the Fish Shell
guidefishpython

Managing Fish shell snippets can get cumbersome. Use Tacklebox and Tackle to bring order to the chaos.

Show full content

So you have installed the Fish shell. Now what?

Rather than manually port all of your Bash/Zsh configuration, you might first consider whether someone has already implemented your desired function in Fish. My Tacklebox and Tackle projects are designed to make it easier for you to utilize existing Fish shell plugins, modules, and shell prompt themes — as well as to have an easy way to add your own. You can read more about it in the Tacklebox announcement post.

Assuming you have followed the installation and usage docs and have installed Tacklebox and Tackle, you can now take advantage of some handy tools, as we’ll see below.

Keeping up-to-date

I often forget which aspects of my computing environment require manual updating, and even when I remember them, recalling the proper update command invocation for each is an additional burden. The up command simplifies this process considerably.

Use Vundle to manage Vim plugins? Update them via:

up vundle

Update Python packages via:

up python

Update Vundle, Python, Homebrew, Fish completions, and others via:

up all
Extract

Similar to the above, it’s often hard to remember which command invocations to use when extracting compressed archives. Now you can simply use one simple command for a wide variety of file types:

extract archive.tar.xz

If you have Pixz and a compatible version of Tar (see respective docs for more detail), there’s also a handy compress command for fast compression of files and directories:

compress your-file-or-directory
Python virtual environments

If you previously used virtualenvwrapper to interact with Python virtual environments via Bash, in Fish you should use the Virtualfish module, which is bundled with Tackle. To create a new project in ~/Projects/ and a new virtual environment in ~/Virtualenvs/:

vf project your-project-name

If you already have an existing project, you can create just the virtual environment via:

vf new your-virtual-env-name

When you want to work on your project and activate its virtual environment:

workon your-project-name
Pip

If, like me, you prefer to restrict Pip to virtual environments so as to avoid accidentally installing a Python package into your global site-packages directory, it can be cumbersome when you occasionally want to invoke Pip globally. You can use the gpip command to make this easier. For example, to see whether Pip, Setuptools, Wheel, or other global packages are outdated:

gpip list --outdated
Closing remarks

These are just a few of the things Tacklebox and Tackle can do to make your Fish shell a more productive place to be. If you have any enhancement ideas, please submit an issue or pull request on the relevant repository. Also, follow me on Twitter to be notified when new handy features are added to Tacklebox and Tackle, and be sure to sign up for early access to Monitorial!

tag:hackercodex.com,2015-09-24:/guide/tacklebox-fish-shell/
Python Development Environment on MacOS Ventura and Monterey
guidepythonmac

While installing Python and Virtualenv on MacOS can be done several ways, this tutorial will guide you through the process of configuring a stock Mac system into a solid Python development environment.

Show full content

While installing Python and Virtualenv on MacOS Ventura and Monterey can be done several ways, this tutorial will guide you through the process of configuring a stock Mac system into a solid Python development environment.

First steps

This guide assumes that you have already installed Homebrew. For details, please follow the steps in the MacOS Configuration Guide.

Python

We are going to install the latest version of Python via asdf and its Python plugin. Why bother, you ask, when Apple includes Python along with MacOS? Here are some reasons:

  • When using the bundled Python, MacOS updates can remove your Python packages, forcing you to re-install them.
  • As new versions of Python are released, the Python bundled with MacOS will become out-of-date. Building Python via asdf means you always have access to the most recent Python version.
  • Apple has made significant changes to its bundled Python, potentially resulting in hidden bugs.
  • Building Python via asdf includes the latest versions of Pip and Setuptools (Python package management tools)

Use the following command to install asdf and Python build dependencies via Homebrew:

brew install asdf openssl readline sqlite3 xz zlib

Next we ensure asdf is loaded for both current and future shell sessions. If you are using Fish shell:

# Load asdf for this session
source (brew --prefix)/opt/asdf/asdf.fish

# Ensure asdf loads for all subsequent sessions
echo source (brew --prefix)/opt/asdf/asdf.fish >> ~/.config/fish/config.fish

# Ensure asdf doesn’t disrupt activated virtual environments
echo 'if set -q VIRTUAL_ENV; source "$VIRTUAL_ENV/bin/activate.fish"; end' >> ~/.config/fish/config.fish

For Zsh (the default shell on MacOS):

. $(brew --prefix asdf)/asdf.sh
echo -e "\n. $(brew --prefix asdf)/asdf.sh" >> ~/.zshrc

Install the asdf Python plugin and the latest version of Python:

asdf plugin add python
asdf install python latest

Note the Python version number that was just installed. For the purpose of this guide, we will assume version 3.11.1, so replace that number below with the version number you actually just installed.

Set the default global Python version:

asdf global python 3.11.1

Confirm the Python version matches the latest version we just installed:

python --version


showgoods();

Pip

Let’s say you want to install a Python package, such as the Virtualenv environment isolation tool. While many Python-related articles for MacOS tell the reader to install Virtualenv via sudo pip install virtualenv, the downsides of this method include:

  1. installs with root permissions
  2. installs into the system /Library
  3. yields a less reliable environment when using Python built with asdf

As you might have guessed by now, we are going to use the asdf Python plugin to install the Python packages that we want to be globally available. When installing via python -m pip […], packages will be installed to: ~/.asdf/installs/python/{version}/lib/python{version}/site-packages/

First, let’s ensure we are using the latest version of Pip and Setuptools:

python -m pip install --upgrade pip setuptools

In the next section, we’ll use Pip to install our first globally-available Python package.

Virtualenv

Python packages installed via Pip are global in the sense that they are available across all of your projects. That can be convenient at times, but it can also create problems. For example, sometimes one project needs the latest version of Django, while another project needs an older Django version to retain compatibility with a critical third-party extension. This is one of many use cases that Virtualenv was designed to solve. On my systems, only a handful of general-purpose Python packages (including Virtualenv) are globally available — every other package is confined to virtual environments.

With that explanation behind us, let’s install Virtualenv:

python -m pip install virtualenv
asdf reshim python

Create some directories to store our projects, virtual environments, and Pip configuration file, respectively:

mkdir -p ~/Projects ~/Virtualenvs ~/.config/pip

We’ll then open Pip’s configuration file (which may be created if it doesn’t exist yet)…

vim ~/.config/pip/pip.conf

… and add some lines to it:

[install]
require-virtualenv = true

[uninstall]
require-virtualenv = true

Now we have Virtualenv installed and ready to create new virtual environments, which we will store in ~/Virtualenvs. New virtual environments can be created via:

cd ~/Virtualenvs
virtualenv project-a

If you have both Python 3.10.x and 3.11.x installed and want to create a Python 3.10.9 virtual environment:

virtualenv -p ~/.asdf/installs/python/3.10.9/bin/python project-b


showgoods();

Restricting Pip to virtual environments

What happens if we think we are working in an active virtual environment, but there actually is no virtual environment active, and we install something via python -m pip install foobar? Well, in that case the foobar package gets installed into our global site-packages, defeating the purpose of our virtual environment isolation.

Thankfully, Pip has an undocumented setting (source) that tells it to bail out if there is no active virtual environment, which is exactly what we want. In fact, we’ve already set that above, via the require-virtualenv = true directive in Pip’s configuration file. For example, let’s see what happens when we try to install a package in the absence of an activated virtual environment:

python -m pip install markdown
Could not find an activated virtualenv (required).

Perfect! But once that option is set, how do we install or upgrade a global package? We can temporarily turn off this restriction by defining a new function in ~/.zshrc:

gpip(){
   PIP_REQUIRE_VIRTUALENV="0" python -m pip "$@"
}

(As usual, after adding the above you must run source ~/.zshrc for the change to take effect.)

If in the future we want to upgrade our global packages, the above function enables us to do so via:

gpip install --upgrade pip setuptools virtualenv

You could achieve the same effect via PIP_REQUIRE_VIRTUALENV="0" python -m pip install --upgrade […], but that’s much more cumbersome to type every time.

Creating virtual environments

Let’s create a virtual environment for Pelican, a Python-based static site generator:

cd ~/Virtualenvs
virtualenv pelican

Change to the new environment and activate it via:

cd pelican
source bin/activate

To install Pelican into the virtual environment, we’ll use Pip:

python -m pip install pelican markdown

For more information about virtual environments, read the Virtualenv docs.

Dotfiles

These are obviously just the basic steps to getting a Python development environment configured. Feel free to also check out my dotfiles.


showgoods();

If you found this article to be useful, feel free to find me on Twitter.

tag:hackercodex.com,2013-10-30:/guide/python-development-environment-on-mac-osx/
Configuring MacOS Ventura and Monterey
guidemac

This MacOS configuration tutorial covers the set-up of a new Mac system, including the installation of Homebrew and command-line tools.

Show full content

MacOS, formerly known as Mac OS X, can be made more powerful with command-line tools such as those available via Homebrew. This tutorial covers installing Homebrew and other useful initial configuration.

Turning off automatic updates

If you prefer to be in control of when updates are downloaded and installed, open System Preferences, go to the Software Update preference pane, and uncheck the relevant boxes.

Un-hide the Library folder

MacOS hides the ~/Library folder by default, but it is easy to make it visible again.

With the Finder as the foremost application, press shift-command-H, command-2, and then command-J, which will bring up a window that configures Finder view options. Check the “Show Library Folder” and close the window. Thanks to the Apple engineers that made this process more user-friendly than it has been in the past.

Compiler

Installing development-related software in the past has required the compiler tool-chain that comes with Xcode. Thankfully, if you don’t need or want Xcode, those compiler tools are now available separately, saving download time and many gigabytes of disk space.

Alternatively, there are some reasons you might want the full version of Xcode:

  • To compile the few tools that won’t compile without Xcode
  • To download and manually compile open-source Mac applications
  • To develop your own Mac/iOS applications

If you don’t need Xcode, you can skip ahead now to the Homebrew section below, since that step will automatically install Apple’s Command Line Tools. If you want to install Xcode, or if you prefer to install the Command Line Tools manually instead of having Homebrew take care of it for you, run the following command in the Terminal:

xcode-select --install

You may be asked whether you want to install Xcode or the command line developer tools, with the latter being the default. If you choose to install Xcode, after installation has completed be sure to launch the Xcode application once to accept the end-user license agreement (EULA).


showgoods();

Homebrew

Sometimes you may need cross-platform software — usually without a GUI and accessible only via the command line — that isn’t readily available via the Mac App Store. Homebrew provides an easy way to install these packages, so let’s fire up Terminal.app and install it:

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

Follow the prompts to download and install Homebrew, entering your administrative password if prompted. Don’t forget to perform any post-installation steps that Homebrew indicates, such as adding brew shellenv configuration to your shell environment. Then run the following command to ensure that there aren’t any potential problems with your environment. Some warnings (if any) are informational and not necessary actionable; it’s just a good idea to at least read through and see if anything looks out of the ordinary.

brew doctor

The following command will update to the latest version of Homebrew and its formulae:

brew update

Let’s use Homebrew to install some useful packages:

brew install zsh-completions ssh-copy-id wget

You can run brew info ssh-copy-id, for example, if you want to know what those packages do.

Some Homebrew formulae recommend post-installation steps. For example, to activate Zsh completions, add the following to your ~/.zshrc:

if type brew &>/dev/null; then
    FPATH=$(brew --prefix)/share/zsh-completions:$FPATH
    autoload -Uz compinit
    compinit
fi

There are many other useful Homebrew commands, all of which can be seen by running man brew in the terminal.

Just the basics

These are obviously just the basics. If you have any interest in Python, have a look at my guide to setting up a Python Development Environment on MacOS.

If you found this article to be useful, feel free to find me on Twitter.


showgoods();

tag:hackercodex.com,2013-10-29:/guide/mac-development-configuration/
Generating Static Sites with Pelican
guidepelicanpython

Pelican is a static site generator, powered by Python. This brief screencast covers Pelican installation and basic usage.

Show full content

Pelican is a static site generator, powered by Python. This brief tutorial covers Pelican installation and basic usage and is presented in screencast form.

For more information and documentation about Pelican, please visit the Pelican Blog.


showgoods();

tag:hackercodex.com,2013-04-24:/guide/pelican-static-site-generator-install/
Install Fish Shell on MacOS and Ubuntu
guidefishmac

Can a command-line shell be Mac-like? Trade in Bash for the Fish shell and watch the magic happen.

Show full content

The Fish shell goes where few command-line shells have gone before, shedding the POSIX baggage of its forebears in favor of simplicity, consistency, and ease-of-use. Much like the Mac creators thought computers should be made to understand how humans work (and not the other way around), Fish observes your past behavior and suggests commands that it thinks you might be trying to execute. Sometimes, those suggestions are so spot-on that it can be downright spooky. Reactions of “How did Fish know that’s what I wanted to do?” are not uncommon.

In this article, we’re going to show how to install the Fish shell on MacOS and Ubuntu, followed by some basic setup steps. Subsequent posts will cover more advanced configuration.

So can a command-line shell be Mac-like? Let’s find out.

What is Fish and why would someone use it instead of another shell?

Fish has a number of advantages over other shells:

  • Fish suggests commands as you type based on history and completions, just like a web browser’s search bar
  • Fish generates completions automatically by parsing your installed man pages
  • Fish has a more intuitive syntax
  • Fish has less historical baggage and technical debt

For additional background information, read:


showgoods();

Installing Fish on MacOS

There are several ways to install Fish on MacOS:

  • traditional .pkg installer
  • standalone Mac application
  • Homebrew
  • manual compilation

The first two options are available from the Fish web site and are straightforward enough to be considered self-explanatory.

That said, if you already use Homebrew (which I recommend) and have configured your environment as noted in the MacOS Setup Guide, then you can install Fish as you would any other package:

brew install fish

If you would prefer to install the latest bleeding-edge version of Fish via Homebrew, run the following instead of the above command:

brew install --HEAD fish

Once installation has completed, add Fish to /etc/shells, which will require an administrative password:

echo "/usr/local/bin/fish" | sudo tee -a /etc/shells

To make Fish your default shell:

chsh -s /usr/local/bin/fish

Now that Fish is installed, you can proceed to the Basic Configuration section below.

Install latest Fish on MacOS from source

If you want to use the latest bleeding-edge version of Fish and already have Xcode installed, use the following steps to install from source:

git clone https://github.com/fish-shell/fish-shell ~/src/fish
cd ~/src/fish
xcodebuild install
ditto /tmp/fish.dst /

Add Fish to /etc/shells, which will require an administrative password:

echo "/usr/local/bin/fish" | sudo tee -a /etc/shells

Make Fish your default shell:

chsh -s /usr/local/bin/fish

Now that Fish is installed, you can proceed to the Basic Configuration section below.


showgoods();

Installing Fish on Ubuntu

On Ubuntu, the easiest way to keep up-to-date is via the offical PPA. If you prefer to install via .deb package, or if you want to install the bleeding-edge version of Fish from source, those instructions are further below.

Install Fish via PPA

The following steps will add the Fish 3.x PPA repository and install Fish:

sudo apt-add-repository ppa:fish-shell/release-3
sudo apt-get update
sudo apt-get install fish

Make Fish your default shell:

chsh -s /usr/bin/fish

Now that Fish is installed, you can proceed to the Basic Configuration section below.

Install Fish on Ubuntu via .deb

The following steps are for the 64-bit version of Ubuntu 22.04 LTS (“Jammy”). If you are using a different version of Ubuntu, you’ll need to retrieve an appropriate .deb package from LaunchPad.

First retrieve and then install the .deb package:

wget https://launchpad.net/~fish-shell/+archive/ubuntu/release-3/+files/fish_3.6.0-1~jammy_amd64.deb
sudo dpkg -i fish_3.6.0-1~jammy_amd64.deb

Make Fish your default shell:

chsh -s /usr/bin/fish

Now that Fish is installed, you can proceed to the Basic Configuration section below.

Install bleeding-edge Fish via PPA

If you prefer, you can keep up-to-date with the bleeding-edge version of Fish via the nightly build PPA. To do so, add the nightly PPA and install Fish:

sudo add-apt-repository ppa:fish-shell/nightly-master
sudo apt-get update
sudo apt-get install fish

Make Fish your default shell:

chsh -s /usr/bin/fish

Now that Fish is installed, you can proceed to the Basic Configuration section below.

Install Fish on Ubuntu from source

Install dependencies:

sudo aptitude install build-essential git autoconf libncurses5-dev libncursesw5-dev gettext

Retrieve source, compile, and install:

mkdir -p ~/src
git clone https://github.com/fish-shell/fish-shell ~/src/fish
cd ~/src/fish
autoconf
./configure --without-xsel
make
sudo make install

Add Fish to /etc/shells:

echo "/usr/local/bin/fish" | sudo tee -a /etc/shells

Make Fish your default shell:

chsh -s /usr/local/bin/fish

Now that Fish is installed, it’s time for some basic configuration.


showgoods();

Basic configuration

The Fish shell should now be installed, but a bit more configuration will prove helpful later.

Create the Fish config directory:

mkdir -p ~/.config/fish

Create initial config file:

vim ~/.config/fish/config.fish

Initial config file contents, which adds /usr/local/bin to the PATH environment variable:

set -g -x PATH /usr/local/bin $PATH

Open a new terminal session, which should now load the Fish shell by default for the first time. You can enter help, followed by the return key, to load user documentation in your default browser.

You can also see your current configuration in your default browser by first entering this command:

fish_config

… and then visiting http://localhost:8000/ in your browser of choice.

Fish can parse your installed man pages and automatically generate completion files for your command-line tools. You should periodically run the following command to update those completions, which are stored in ~/.config/fish/completions by default:

fish_update_completions

Last but not least, running:

echo "set -gx fish_greeting ''" >> ~/.config/fish/config.fish

… will eliminate the Fish welcome message that appears by default. If you want to add your own custom welcome message instead of removing the message entirely, insert your preferred text inside the '' marks.

Getting back to Bash

If you want to temporarily switch to the Bash shell for a single session, run:

bash

When you are done with your Bash session, type exit to return to your Fish shell.

If you decide Fish isn’t for you and want to permanently revert your default shell back to Bash:

chsh -s /bin/bash

… will switch your default shell to Bash.

Taking it to the next level

With Fish as your default shell, you may find that customizations you’ve made to your Bash environment are not present in Fish. The good news is that it’s easy to re-create those customizations — and create new enhancements — via Tacklebox, which allows you to easily use community-curated modules, plugins, and themes so you don’t have to create them yourself.

If you found this article to be useful, feel free to follow me on Twitter.


showgoods();

tag:hackercodex.com,2013-01-09:/guide/install-fish-shell-mac-ubuntu/
Speed Up Compression via Parallel BZIP2 (PBZIP2)
guide

Did you know you can speed up your bzip2 compression time by an order of magnitude? If you have multiple cores, follow this guide to enable massive compression speed gains.

Show full content

By pure chance one morning, I came across a post that mentioned PBZIP2. Having never heard of it, of course I had to look it up. Crikey. File this one under “Why Didn’t Someone Tell Me About This Earlier?!”

“Wait a minute,” I said aloud to nobody in particular. “BZIP2 doesn’t support symmetric multi-processing? And there’s an alternate implementation that does take advantage of multiple CPUs?”

“Whiskey. Tango. Foxtrot.”

And after a few tests, I’ll be tarred and feathered if it ain’t true: the speed improvement was, as promised, linear to the number of cores.

Installation

To install it via Homebrew on MacOS:

brew install pbzip2

To install it on Ubuntu or Debian:

sudo apt install pbzip2

The pbzip2 binary should now be available. Refer to the manpage for the gory details.


showgoods();

Testing

Using a 91 MB tar archive as my test file, I ran the following commands on a quad-core 2.93 GHz i7 running Mac OS X 10.7 (Lion) to see whether there was indeed any improvement in compression speed:

time bzip2 -k testfile.tar
time pbzip2 -k testfile.tar

The results: 18.7 seconds for bzip2, and… wait for it… 3.5 seconds for pbzip2. That represents an 81% reduction in compression time and a five-fold increase in speed in this particular test.

While decompression speed increases weren’t nearly as dramatic, pbzip2 decompression appears to faster than stock bzip2.

New Aliases

I don’t want to have to remember to specifically use the pbzip2 command, so I decided to add some aliases. First, let’s detect whether pbzip2 is installed and available:

# Check to see if pbzip2 is already on path; if so, set BZIP_BIN appropriately
type -P pbzip2 &>/dev/null && export BZIP_BIN="pbzip2"
# Otherwise, default to standard bzip2 binary
if [ -z $BZIP_BIN ]; then
  export BZIP_BIN="bzip2"
fi

Using the above logic, I set bz as an alias to pbzip2 if available, and if not, to bzip2:

alias bz=$BZIP_BIN

I usually compress directories more often than individual files, so I added some commands to quickly compress directories and expand bzipped tarballs:

tarb() {
  tar -cf "$1".tbz --use-compress-prog=$BZIP_BIN "$1"
}
untarbzip() {
  $BZIP_BIN -dc "$1" | tar x --exclude="._*"
}
alias buntar=untarbzip

Usage:

bz myfile
tarb mydirectory
buntar mytarball.tbz
Got a better method?

Have you had any experience with parallelized bzip2 compression? Find me on Twitter and let me know.


showgoods();

tag:hackercodex.com,2012-05-30:/guide/parallel-bzip-compression/
How to Stop Your ISP from Hijacking Your DNS Servers
guidenetwork

Remember when Internet service providers began redirecting requests for non-existent domains to their own ad-filled pages? Turns out they’ve upped their game. Even if you’ve switched your DNS settings away from the servers provided by your ISP, some ISPs have still figured out a way to hijack your DNS. This quick tutorial shows how to put a stop to their latest shenanigans.

Show full content

Remember when Internet service providers began redirecting requests for non-existent domains to their own ad-filled pages? Turns out they’ve upped their game. Even if you’ve switched your DNS settings away from the servers provided by your ISP, some ISPs have still figured out a way to hijack the NXDOMAIN response. This quick tutorial shows how to put a stop to their latest shenanigans.

Back in 2009, many folks noticed that if they mistyped a web address and tried to visit a non-existent domain, instead of seeing the usual “Server not found” error message, they instead were served an ISP-branded search page filled with ads. This insidious new trend on the part of Comcast and other Internet service providers redirects requests for unresponsive servers and non-existent domains to their own ISP-branded, ad-laden search pages. These ISPs claim that users can opt out of the hijacking, but you’d have to perform the opt-out procedure on every browser and computer in your house, and even then the opt-out expires after a while, forcing you to hassle with it all over again each time the opt-out period expires. Understandably outraged, many customers of these ISPs responded by changing their DNS servers away from their ISP, instead using alternative domain name resolution servers provided by Google. Not only does this restore proper network behavior and eliminate the sleazy advertising, but utilizing alternate DNS servers also often provides faster browsing performance due to faster DNS lookups.

It turns out, however, that ditching your ISP’s DNS servers may not be enough. Recently, the same ISP DNS hijacking shenanigans have been observed even when DNS settings are explicitly configured to use non-ISP servers such as Google’s. (In fact, all tests below were performed with DNS servers set to 8.8.8.8 and 8.8.4.4.) How can you tell whether your ISP is interfering with your DNS? Easy:

$ ping nonexistentdomain.tld
PING nonexistentdomain.tld (184.106.15.239): 56 data bytes
64 bytes from 184.106.15.239: icmp_seq=0 ttl=236 time=1200.926 ms
64 bytes from 184.106.15.239: icmp_seq=1 ttl=236 time=71.050 ms
64 bytes from 184.106.15.239: icmp_seq=2 ttl=236 time=72.768 ms
[...]

Whoa, wait a minute. How is a non-existent server responding to pings, you ask? It isn’t. Your ISP is responding instead via a fake IP address. Lovely. Thanks for the value-added service, Time Warner! Sarcasm aside, at least now we know the primary IP address (184.106.15.239) that Time Warner is using to help break the Internet. Let’s find out if there are any other IP addresses we should know about:

$ nslookup nonexistentdomain.tld
Server:     192.168.1.1
Address:    192.168.1.1#53

Non-authoritative answer:
Name:   nonexistentdomain.tld
Address: 184.106.15.239
Name:   nonexistentdomain.tld
Address: 204.232.137.207

Great — we’ve just discovered another bogus IP address: 204.232.137.207. So what do we do with these two IP addresses?


showgoods();

If you have a router running DD-WRT or Tomato, then you are in luck, because most likely you’ll have a tool called Dnsmasq at your disposal. Assuming you have DD-WRT running on your router, the following configuration steps should make short work of the offending IP addresses and the meddling they represent:

  1. Visit your DD-WRT’s configuration page, often at http://192.168.1.1/
  2. Navigate to Services > Services > DNSMasq and make sure the “DNSMasq” radio button is enabled.
  3. Insert the following into the “Additional DNSMasq Options” textarea field:

(Be sure to replace the IP addresses with the offending digits proferred by your ISP.)

bogus-nxdomain=184.106.15.239
bogus-nxdomain=204.232.137.207

Last but not least, click the “Apply Settings” button at bottom. With the router configuration completed, let’s see if we notice any change in network behavior:

$ ping nonexistentdomain.tld
ping: cannot resolve nonexistentdomain.tld: Unknown host

$ nslookup nonexistentdomain.tld
Server:     192.168.1.1
Address:    192.168.1.1#53

** server cannot find nonexistentdomain.tld: NXDOMAIN

Success! That’s what’s supposed to happen when you query a domain that has no associated IP address. We have, once again, thwarted Big Telecom from breaking the Internet.

So what do you do if you don’t have Dnsmasq running on your router and can’t easily flash your router with DD-WRT or Tomato in order to get it? Most likely you’ll have to manually install and configure Dnsmasq on your computer, the details of which are well beyond the scope of this article. Aside from the added setup complexity, installing Dnsmasq on an individual computer won’t solve the problem for other computers you may have on your network. So this is really a problem that is best solved at the router level. If you don’t have the technical wherewithal to flash your router with DD-WRT or Tomato, Buffalo Technology makes a line of routers that come with DD-WRT pre-installed: (aff links)

Hopefully your ISP is a better net citizen than Comcast or Time Warner, but if not, now you have the tools to fight back. Tell us about your personal experiences: have you encountered this problem? If so, how did you solve it?


showgoods();

tag:hackercodex.com,2012-05-02:/guide/how-to-stop-isp-dns-server-hijacking/
Set Up Python and Install Django on Mac OS X Lion 10.7
guidepythondjangomac

Installing Django and other Python tools on Mac OS X 10.7 Lion can be done any number of ways. While there’s no best or perfect configuration, this tutorial will guide you through the process of configuring a stock Lion installation into a rockin’ Python / Django development system.

Show full content

NOTE: This guide was written for Lion 10.7 and has since been superceded by these new guides:

First steps

Lion has done away with the “Sites” folder by default, but it’s easy to add it back — the custom icon will even show up automatically. Use the Finder, or enter the following in a Terminal session:

mkdir ~/Sites

Another change is the hidden ~/Library folder. We can make it visible again with the following command (which gets overridden by OS updates and must be run again afterwards):

chflags nohidden ~/Library/

Since Lion is a full 64-bit system, we’ll save some headaches by letting our compiler know that all compilation should assume 64 bits. Open ~/.bash_profile …

vim ~/.bash_profile

… and add:

# Set architecture flags
export ARCHFLAGS="-arch x86_64"

With those first steps out of the way, now it’s time to get the necessary compilation tools in place.


showgoods();

Compiler

Installing development-related software in the past has required the compiler tool-chain that comes with Xcode. Thankfully, if you don’t need or want Xcode, those compiler tools are now available separately, saving download time and many gigabytes of disk space. Assuming you have your Apple ID credentials handy, head over to the Developer Downloads area, download the Command Line Tools for Xcode, and install it.

Alternatively, if you need Xcode for Mac/iOS app development or find yourself occasionally using it to manually compile open-source Mac applications, download Xcode from either the Developer Downloads area or the Mac App Store. Make sure you’re on a high-bandwidth connection, because Xcode is a massive beast. Once you’ve installed Xcode, launch the Xcode application, visit the app preferences, find the “Downloads” pane, and download the above-mentioned Command Line Tools from within the Xcode application.

Homebrew

Sometimes you may need cross-platform software — usually without a GUI and accessible only via the command line — that isn’t readily available via the Mac App Store. As someone who used MacPorts for years, I can’t begin to explain the relative awesomeness that is Homebrew. It’s an indispensable tool that should be in every Mac developer’s arsenal, so let’s fire up Terminal.app and install it:

ruby -e "$(curl -fsSL https://raw.github.com/mxcl/homebrew/master/Library/Contributions/install_homebrew.rb)"

That’s it — Homebrew is now installed. While it should have the latest version of Homebrew and its formulae, let’s run the update command just in case:

brew update

If the “brew update” command produces an error, make sure /usr/local is owned by you and not by root:

sudo chown $USER /usr/local
brew update

The Homebrew wiki has a full command list and a bunch of other useful information, but here’s a quick command to install some packages that I often find useful:

brew install bash-completion byobu ssh-copy-id wget

You can run “brew info byobu”, for example, if you want to know what those packages do.

Python site-packages

Let’s say you want to install a Python package, such as the fantastic virtualenv environment isolation tool. Nearly every Python-related article for Mac OS X tells the reader to install it via sudo easy_install virtualenv. Here’s why I don’t do it that way:

  1. installs with root permissions
  2. installs into the global /Library instead of the user’s
  3. “Distribute” has less bugs than the default legacy easy_install

If I install a Python package and decide I want to delete it, I like having the option to use the Finder to drag it to the Trash without any permission-related complaints. Plus, keeping the Python packages isolated to the user account just makes more sense to me. Last but not least, Distribute is a fork of Setuptools/easy_install that aims to be more reliable with less bugs.

Traditionally, I’ve always used the --user flag to install Python packages into ~/.local, a behavior that was consistent across Macs, Linux, and other UNIX systems. It seems Lion has changed this behavior, however, installing into ~/Library/Python/2.7 when it encounters the --user flag. Since I prefer to have this location remain consistent across the various systems I encounter, I changed the flag from --user to the more specific --prefix=~/.local. Whichever you choose, please keep in mind that the instructions here assume the latter.

With that tangent behind us, let’s install Distribute:

mkdir -p ~/.local/lib/python2.7/site-packages
wget http://pypi.python.org/packages/source/d/distribute/distribute-0.6.28.tar.gz
tar -xzf distribute-0.6.28.tar.gz
cd distribute-0.6.28
python setup.py install --prefix=~/.local

The only disadvantage of installing into ~/.local is that we need to add some locations to the PATH and PYTHONPATH environment variables. Let’s edit our .bash_profile…

vim ~/.bash_profile

… and add a few lines:

# Path ------------------------------------------------------------
if [ -d ~/.local/bin ]; then
  export PATH=~/.local/bin:$PATH
fi

# Python path -----------------------------------------------------
if [ -d ~/.local/lib/python2.7/site-packages ]; then
  export PYTHONPATH=~/.local/lib/python2.7/site-packages:$PYTHONPATH
fi

# Load in .bashrc -------------------------------------------------
if [ -f ~/.bashrc ]; then
  source ~/.bashrc
fi

Let’s load those directives now via:

touch ~/.bashrc
source ~/.bash_profile

Lion’s easy_install is normally located in /usr/bin, so let’s make sure that our local version is the one that’s used by default:

which easy_install

Assuming the response is ~/.local/bin/easy_install, then we’re all set!


showgoods();

virtualenv and virtualenvwrapper

Python packages installed to ~/.local are indeed local to the user, but they are also global in the sense that they are available across all of a given user’s projects. That can be convenient at times, but it also creates problems. For example, sometimes one project needs the latest version of Django, while another needs Django 1.3 to retain compatibility with a critical third-party extension. This is precisely the problem that virtualenv was designed to solve. On my systems, virtualenv, virtualenvwrapper, and Mercurial are the only Python packages that are always available — every other package is confined to its virtual environment.

Let’s install virtualenv and its companion virtualenvwrapper:

easy_install --prefix=~/.local virtualenv virtualenvwrapper

We’ll then open/create the ~/.bashrc file…

vim ~/.bashrc

… and add some lines to it:

# Turn on advanced bash completion if the file exists
if [ -f /usr/local/etc/bash_completion ]; then
  . /usr/local/etc/bash_completion
fi

# Locate virtualenvwrapper binary
if [ -f ~/.local/bin/virtualenvwrapper.sh ]; then
    export VENVWRAP=~/.local/bin/virtualenvwrapper.sh
fi

if [ ! -z $VENVWRAP ]; then
    # virtualenvwrapper -------------------------------------------
    # make sure env directory exists; else create it
    [ -d $HOME/sites/env ] || mkdir -p $HOME/sites/env
    export WORKON_HOME=$HOME/sites/env
    source $VENVWRAP

    # virtualenv --------------------------------------------------
    export VIRTUALENV_USE_DISTRIBUTE=true

    # pip ---------------------------------------------------------
    export PIP_VIRTUALENV_BASE=$WORKON_HOME
    export PIP_REQUIRE_VIRTUALENV=true
    export PIP_RESPECT_VIRTUALENV=true
    export PIP_DOWNLOAD_CACHE=$HOME/.pip/cache
fi

Let’s re-load our bash environment again:

source ~/.bash_profile

I also add two customizations to virtualenv’s postactivate script, which defines what happens after activating a virtual environment:

vim ~/sites/env/postactivate

Add the following lines, taking note of the comments to see what benefits they offer:

proj_name=${VIRTUAL_ENV##*/}

# Add the active project to the PYTHONPATH
if [ -d ~/sites/env/$proj_name/lib/python2.7/site-packages ]; then
  add2virtualenv ~/sites/env/$proj_name/lib/python2.7/site-packages
fi

# "cd" into the virtualenv, or its "project" folder if there is one
if [ -d ~/sites/env/$proj_name/project ]; then
  cd ~/sites/env/$proj_name/project
else
  cd ~/sites/env/$proj_name
fi

Now we have virtualenv and virtualenvwrapper installed and ready to create new virtual environments, which will be stored in ~/sites/env/.


showgoods();

Version control

Lion comes with git, which is a welcome addition. I’m partial to Mercurial, so for those that want both options, the following command will do the trick:

easy_install --prefix=~/.local Mercurial

At a minimum, you’ll need to add a few lines to your .hgrc file in order to use Mercurial:

vim ~/.hgrc

The following lines should get you started; just be sure to change the values to your name and email address, respectively:

[ui]
username = YOUR NAME <address@example.com>

To test whether Mercurial is configured and ready for use, run the following command:

hg debuginstall

If the last line in the response is “No problems detected”, then Mercurial has been installed and configured properly.

Creating virtual environments

Let’s create a virtual environment called “foobar”:

mkvirtualenv foobar

That should create a new virtual environment and automatically switch our present working directory to that new foobar environment.

In the future, when you want to work on a project contained in a virtual environment, use the “workon” command followed by the name of the virtual environment:

workon foobar

That will activate the “foobar” virtual environment, and if you’ve made the changes I recommended earlier to the “postactivate” script, you should be taken directly to the virtual environment’s directory at ~/sites/env/foobar. If not, you can always get there via the “cdvirtualenv” command, which will take you to the currently-active virtual environment’s home.


showgoods();

First Django project

Assuming our current working directory is our new “foobar” virtual environment, let’s create a folder within called “project” that will contain all of our to-be-versioned files:

mkdir project

While the quick way to install Django would be…

pip install Django

… a better way is to define our project’s dependencies in a requirements file:

vim project/requirements.txt

Our requirements at this point are very simple — just Django. So the contents of our requirements.txt file should just be:

Django

We can then install Django via:

pip install -r project/requirements.txt

We’ll use Django’s “startproject” command to create a new site within our “project” folder:

django-admin.py startproject mysite project/

We can now start Django’s development web server…

cd project
python manage.py runserver

… and see the results in our web browser. For those that are new to Django, the Django Tutorial is a good place to learn how to continue building your project.

First commit

Now that you have a Django project started, use your preferred version control system to make your first commit. For Mercurial, that would be:

hg init project
cd project
hg add
hg commit -m "Initial commit"

By versioning your projects from the very beginning, you’ll always know how (and hopefully why) you’ve made your changes along the way.

Dotfiles

While I’ve posted excerpts of my dotfiles above, you can get the whole enchilada on GitHub.

Phew!

Congrats! It takes a bit of time to set up a new system, but it’s well worth the journey. These are the tools of our trade, and we use them every day, so it makes sense to make them as efficient as possible.


showgoods();

tag:hackercodex.com,2011-08-30:/guide/python-install-django-on-mac-osx-lion-10.7/