Bash history synchronization

Bash is my go to shell. I've tried fish; I've heard about zsh; but Bash is my go to.

I really like command history (pressing up arrow or Ctrl+R) and there are a few specific behaviors that I want in my history:

  1. If I have multiple terminals open, I want history shared across them.
  2. If I run the same command multiple times, it should be in my history once.
  3. My history should stick around forever.
  4. The last command, I entered should be the first thing I see when I press up arrow.
  5. Race conditions of long-running commands shouldn't erase history entries.

Turns out all of this is a little tricky with bash, but I've mostly managed it:

export HISTSIZE="INFINITE"
export HISTFILESIZE="INFINITE"
shopt -s histappend
shopt -s cmdhist
alias histsync='history -a && history -c && history -r && history | sort -k2 -k1nr | uniq -f1 | sort -n | tr -s " " | cut -d " " -f3- > ~/.tmp$$ && history -c && history -r ~/.tmp$$ && history -w && rm ~/.tmp$$'
export PROMPT_COMMAND="${PROMPT_COMMAND:+$PROMPT_COMMAND$'\n'}histsync"

Read more…

Slowcooker Yogurt

Some jars of homemade yogurt

I have a 14 month old daughter, a wife that likes yogurt with granola, and I kind of like the stuff too. Needless to say, we go through a lot of yogurt in my house. Specifically, we go through a lot of plain, whole milk, greek yogurt.

We were recently visiting my wife's aunt and uncle (my daughter's graunt and gruncle), and we had yogurt most mornings. They use an EasiYo to make their yogurt, which piqued my curiosity.

Fancy yogurt is pretty expensive at the store, upwards of $7 or $8 per 32oz container. Yogurt is just fermented milk and I've fermented plenty of things before. I should be able to make yogurt, right?

So, how about EasiYo? Turns out it's not that much cheaper.

We can do better, let's ask the Internet.

Turns out it's pretty straightforward; I just finished our second batch yesterday. It also turns out to be really good, and it's less than $2 per 32oz (milk choice depending).

Read more…

An AWS wat?!

tl;dr different AWS regions have different APIs.

I've been using AWS via boto3 a bunch lately and testing can be a bit of a pain. To my great joy, there turns out to be a mock aws implementation: moto.

Moto support for boto is pretty good but support for boto3 is still a bit of a work in progress. In testing, I was finding a lot of functionality to be broken, in spite of it working for other people. Through some poking and digging, I discovered that the failures depended on the region.

Here's a chunk of test code that illustrates the issue:

test_moto_boto3_regions.py (Source)

import io

import boto3
import moto
import pytest


@pytest.mark.parametrize('region_name', [
    'us-east-1',
    'us-west-1',
    'us-west-2',
    'eu-west-1',
    'eu-cental-1',
    'ap-northeast-1',
    'ap-northeast-2',
    'ap-southeast-1',
    'ap-southeast-2',
    'sa-east-1',
])
@moto.mock_s3
def test_mock_s3(region_name):
    s3session = boto3.Session(region_name=region_name)
    s3res = s3session.resource('s3')
    s3bucket = s3res.Bucket('test_bucket')
    s3bucket.create()
    s3obj = s3res.Object('test_bucket', 'test_object.txt')
    s3obj.put(Body=io.BytesIO(b'abc'))
    data = s3obj.get()['Body'].read()
    assert b'abc' == data

Punchline: A call to "py.test test_moto_boto3_regions.py" gives:

test_moto_boto3_regions.py .FFF.F.FFF

====================== 7 failed, 3 passed in 0.97 seconds ======================

Why the heck are the api calls of boto3 dependent on the region being called?

Internet Time Now script

On account of being mentioned by Reply All, I've been listening to back episodes of [TLDR]. Listening to #15 - Internet Time caught my attention and made me aware of Swatch Internet Time. It's kind of impractical but also kind of fun, especially as I've been a little annoyed at recording times across timezones for something meant to persist, like this blog.

For fun, I whipped up a quick python implementation:

import datetime
import decimal

def decimal_time(ts):
    mus_ts = (ts.hour * 3600 + ts.minute * 60 + ts.second) * 1000000 + ts.microsecond
    mus_day = 24 * 3600 * 1000000
    dec_time = decimal.Decimal(mus_ts) / decimal.Decimal(mus_day)
    return dec_time * 1000

def internet_time_now(precision=0):
    precision = int(max(0, min(25, precision)))
    precision = 0 if precision < 1 else int(precision)
    format_len = 3 if precision < 1 else 4 + precision
    format_str = '@{{:0{l:d}.0{p:d}f}}'.format(l=format_len, p=precision)
    it_utc_p1 = datetime.datetime.utcnow() + datetime.timedelta(hours=1)
    return format_str.format(decimal_time(it_utc_p1))

Or, if you don't care about precision:

import datetime

def decimal_time(ts):
    s_ts = ts.hour * 3600 + ts.minute * 60 + ts.second
    s_day = 24 * 3600
    return int(1000 * s_ts / s_day)

def internet_time_now():
    it_utc_p1 = datetime.datetime.utcnow() + datetime.timedelta(hours=1)
    return '@{:03d}'.format(decimal_time(it_utc_p1))

Fixing Nikola Footnote Locations

Personally, I prefer to intersperse my footnote declarations with the text that is being footnoted when writing my. For example:[1]

[1] This is just an example.
I might want to write something[#]_ where there's a footnote there.

.. [#] I put the footnote definition here.

And then I continue on with the rest of my writing.

Wherever they are declared, I prefer to have all of my footnotes appear at the end of my posts. By default, Nikola puts the footnotes in wherever they are declared. A simple snippet of javascript can be used to fix the locations of footnotes:

$(document).ready(function() {
    $('.footnote').each(function(i, el) {
        $(el).appendTo(
            $(el).closest('article'));
    });
});

Simply wrap in a <script> tag and include in the BODY_END section of conf.py

A Fresh Start

It has been a very long time since I've done any serious work on my website. Now, that changes.

I've migrated all of gwax\.(com|org|net) to Google Cloud infrastructure.

Now, I'm embarking on a thorough site rewrite using Nikola for the static site management.

Bonus: free blogging feature that I probably won't use very much.

Entries from before this point have been dredged from my archives.

Will O' The Wisp

Continuing my earlier work in the realm of mixology, I would like to present my second cocktail invention. The invention of this cocktail is the result of playing around with gin, Chartreuse, St. Germain, and various other liqueurs in an attempt to make something tasty. This cocktail earns its name, Will O' The Wisp, from its faint, ghostly, green color.

Ingredients

  • 3/4 oz Green Chartreuse
  • 3/4 oz St. Germain
  • 3/4 oz White Vermouth
  • 1 dash Lavender Bitters
  • 3 oz Dry Gin
  • 1/4 oz Herbsaint or Absinth

Recipe

  1. Pour the Chartreuse, St. Germain, Vermouth, Bitters, and Gin into a cocktail shaker
  2. Pour the Herbsaint/Absinth into a chilled cocktail glass
  3. Swirl the cocktail glass, coating the sides, and pouring off any excess Herbsaint/Absinth
  4. Add ice to the cocktail shaker and shake
  5. Pour shaken cocktail into the prepared glass

Notes

The Herbsaint/Absinth can be skipped, though I don't recommend it. The Lavender Bitters are also optional but very highly recommended. I would recommend stirring this cocktail (instead of shaking) as the resulting beverage has a very different appearance.

Ironhide

Some number of weeks ago, having discovered Maraschino liqueur, I concocted a variation on my beloved Manhattan. I have been meaning to write up the recipe here for a while but had been stuck on coming up with a name; I needed a name befitting a strong whiskey cocktail with connections to myself and the color red. Having thought for quite a while and come up with a bunch of names that were already taken by other cocktails, I settled on naming the drink after the grizzled, old Autobot, Ironhide. So, without further ado:

Ironhide recipe

  • 3 oz Bourbon whiskey
  • 3/4 oz Maraschino
  • 1/4 oz grenadine
  • 2 dashes Angostura bitters
  • 1 Maraschino cherry

Serve shaken or stirred with ice in a cocktail glass; garnish with the Maraschino cherry.

Notes

I have mostly been drinking these on the rocks, which is an acceptable but inferior variation. Being a Manhattan-like cocktail, up-high is really the correct way to serve an Ironhide.

Corn syrup based grenadine or "maraschino" cherries will ruin the flavors imparted by the bitters and Maraschino; you will make a better cocktail by skipping the grenadine and cherry than using cheap, fake ones.