tag:tech-notes.maxmasnick.com,2013:/posts Technical Notes 2019-11-07T15:43:12Z by Max Masnick tag:tech-notes.maxmasnick.com,2013:Post/1442542 2019-08-08T16:59:00Z 2019-08-08T17:00:39Z Storing and retrieving passwords in bash scripts from the macOS keychain

It's often convenient to store a password in the macOS system keychain and retrieve it inside a shell script.

Here's the bash command for setting a password:

security add-generic-password -s "Keychain item name here" -a "username here"

Then enter your password when prompted.

After you run this once, you can retrieve the password in a script like this:

PASSWORD=`security find-generic-password -s "Keychain item name here" -a "username here" -w`

You can then use $PASSWORD whenever you need the password in your script.

Max Masnick
tag:tech-notes.maxmasnick.com,2013:Post/1442108 2019-08-07T14:44:11Z 2019-11-07T15:43:12Z Backing up OneNote notebooks By default, OneNote stores notebooks on OneDrive in a “Documents/“ folder. But the notebooks are not downloaded locally by the OneDrive sync client — the sync client simply downloads “.url” link files that take you to the notebook on onenote.com.

However, there is an easy way to grab a backup. Use the “Download” option on onedrive.com to download a .zip file of the entire “Documents/“ folder. This .zip will have all your notebooks in the open, documented OneNote file format.

Update (November 7, 2019): Thanks to David Mytton for pointing out that this only works for personal Office365 accounts. If you have a business account, OneDrive will store your OneNote notebooks in a "Notebooks/" folder rather than a "Documents/" folder, and it will not let you download this folder. This is a known issue and Microsoft is working to resolve it.
Max Masnick
tag:tech-notes.maxmasnick.com,2013:Post/1393793 2019-04-04T17:38:55Z 2019-04-04T17:38:55Z Unroll tweetstorm bookmarklet

window.location.href = 'https://threadreaderapp.com/search?q='+encodeURI(window.location.href)

You can use this page to convert the above JavaScript to a bookmarklet.

Max Masnick
tag:tech-notes.maxmasnick.com,2013:Post/1378813 2019-02-26T14:19:29Z 2019-02-26T14:19:29Z Using AppleScript to activate the "Choose which speakers to use" button in iTunes

Once the menu is active, you can use the arrow keys to navigate up and down, and return to select a given speaker. This allows you to tell iTunes to control a Homepod or other AirPlay 2 speaker from the keyboard.

Unfortunately there is no way I can find to automatically select a specific speaker – you have to manually do it with the arrow keys.

Max Masnick
tag:tech-notes.maxmasnick.com,2013:Post/1368363 2019-01-29T21:17:10Z 2019-07-13T13:03:51Z Using Pipenv with R Markdown and reticulate

R Markdown is very nice way to write literate R code. Recently, reticulate became available, which bridges R and Python in R Markdown documents.

If you use Pipenv for Python dependency management, here's how you get reticulate to use the proper Python executable:

venv <- system("pipenv --venv", inter = TRUE)
use_virtualenv(venv, required = TRUE)

The py_config() command should print out the path to the Python executable in the virtualenv created by Pipenv.

Max Masnick
tag:tech-notes.maxmasnick.com,2013:Post/1363202 2019-01-14T13:35:16Z 2019-01-14T13:35:16Z Ruby: Using Bundler Without a Gemfile

A very handy tip from Victor Afanasev:

Did you know that you can use Bundler inside single Ruby script (without Gemfile) and automatically install required dependencies for it?

# example.rb

require 'bundler/inline'

gemfile do
  source 'https://rubygems.org'
  gem 'rest-client'
  gem 'nokogiri'


body = RestClient.get("https://www.reddit.com/r/ruby/").body

puts "Posts from r/ruby front page:"
Nokogiri::HTML(body).xpath("//div[contains(@class, 'scrollerItem')]//h2").each do |h2|
  puts h2.text.strip
Max Masnick
tag:tech-notes.maxmasnick.com,2013:Post/1360043 2019-01-04T01:19:55Z 2019-01-04T01:19:56Z Customizing the padlock image for Curtain Mode with macOS screen sharing

By default, the Mac will display a giant padlock image when "Curtain Mode" is engaged with the Screens VNC app or macOS's built-in screen sharing capability:

I wanted to remove the padlock to avoid burn-in during long screen sharing sessions. I found this Apple Discussions post with the following instructions for overriding the default image:

  • Create a picture using a graphics program, such as AppleWorks.
  • Save the picture in PICT, TIFF, GIF, JPEG, or any other QuickTime-compatible static image format.
  • QuickTime-compatible movies or QuickTime VR objects cannot be used.
  • Name the picture "Lock Screen Picture".
  • Copy the "Lock Screen Picture" file to /Library/Preferences/ on the client computer.

I was very dubious that it would work, but incredibly it does! If you save a plain black .tiff like this one as /Library/Preferences/Lock Screen Picture.tiff, the padlock image will disappear.

Max Masnick
tag:tech-notes.maxmasnick.com,2013:Post/1339318 2018-11-02T16:04:51Z 2018-11-02T16:07:17Z Fixing files that should have been pointers in LFS but weren't

There is a relatively easy fix for a message from git lfs like:

Encountered n file(s) that should have been pointers, but weren't

If the files in question are already on a remote and you don't want to rewrite history, run:

git lfs migrate import --no-rewrite path/to/file.ext

This will create a new commit moving path/to/file.ext to LFS.

If you do need to rewrite history, see the documentation for migrating data to LFS.

To check whether this worked, run:

git lfs ls-files | grep path/to/file.ext

You should see an entry for path/to/file.ext in the resulting output.

Max Masnick
tag:tech-notes.maxmasnick.com,2013:Post/1314602 2018-08-23T21:51:28Z 2018-08-23T21:51:29Z Work-around for broken Pocket bookmarklet

I've found that Pocket's bookmarklet is not reliable in Safari and Safari Technology Preview due to browser security measures against 3rd party cookies. This results in their official bookmarklet asking me to "Please login" every time I try to use it.

Fortunately, there is an easy work-around with a very simple bookmarklet:

window.location.href = 'https://getpocket.com/edit?url='+encodeURI(window.location.href)

You can use the Bookmarklet Maker to turn this code into an actual bookmarklet.

Max Masnick
tag:tech-notes.maxmasnick.com,2013:Post/1280256 2018-05-04T16:06:06Z 2019-08-04T12:03:29Z Fix FileVault's "Some users are unable to unlock the disk" error when the APFS boot disk is manually encrypted with a "Disk Password"

This happened to me because I restored my boot disk from a full disk clone (thanks to a bad macOS update installation). I didn't want to restore to an unencrypted disk, so when I booted from my backup disk to do the restore, I used Disk Utility to encrypt my internal boot disk with a password.

After encrypting and then cloning the backup to my boot drive, I was greeted with a screen like this on my first boot from my boot drive:

Fine, no problem. I entered my disk password, and the normal login screen showed up. I entered my user password and everything was working...except I could not re-enable unlocking my disk with my user's password:

After searching around for how to fix failure of "Enable users" when "Some users are unable to unlock the disk", I discovered that there are a set of command line utilities for dealing with FileVault and I was able to fix the problem by decrypting the disk and then re-enabling FileVault.

Here's the command to decrypt: diskutil apfs decryptVolume /dev/disk1s1

To get "/dev/disk1s1", I simply looked at the info for my hard drive ("HD") in Disk Utility. (Normally this would be named "Macintosh HD", but I always rename mine.)

Then I simply re-enabled FileVault through System Preferences.

Warning: Messing around with disk encryption (or messing around with anything involving your boot disk) is risky. Always have a known good backup before you try anything like this, and proceed at your own risk – I am not responsible if you break your disk trying to follow these instructions.

Max Masnick
tag:tech-notes.maxmasnick.com,2013:Post/1262798 2018-03-18T20:12:53Z 2018-03-18T20:12:53Z Unroll/extract/read tweets from a tweetstorm

I've found a few decent ways to extract all the tweets from a "tweetstorm" for easier reading or quoting:

Max Masnick
tag:tech-notes.maxmasnick.com,2013:Post/1262081 2018-03-16T17:15:32Z 2018-03-16T17:15:32Z PyCharm: View DataFrame or Series using SciView from the "Evaluate" window with a keyboard shortcut

When using PyCharm for debugging data science code, I often want to view a Pandas DataFrame from PyCharm's interactive debugger. It took me a bit to figure out how to do this from the keyboard — here's what I do:

  1. While debugging, open the "Evaluate" window (bound to cmd-; in my configuration).
  2. Type in the name of the variable for the DataFrame and press enter, which gives me this:
  3. Now the question is how to activate the "View as DataFrame" button with the keyboard (see green arrow above). Turns out you can bind "View as Array" to a keyboard shortcut, which will also trigger "View as DataFrame". So I tab from the "Expression" text field to the "Results" area and then hit my "View as Array" shortcut (cmd-enter). This opens the DataFrame in SciView.

Here's the "View as Array" keyboard shortcut configuration:

I've found "floating mode" to work best with SciView. cmd-w will close SciView in floating mode, but for some reason when I do this, the "Evaluate" window will lose focus and I can't figure out how to focus it again without mousing. Keyboard Meastro to the rescue here:

Max Masnick
tag:tech-notes.maxmasnick.com,2013:Post/1248798 2018-02-16T22:18:34Z 2018-02-16T22:18:34Z Open tweet in Twitterific bookmarklet

Source: var x = /twitter.com\/.*\/status\/([0-9]+)/.exec(window.location.href); if(x == null) {alert("Doesn't look like this is a tweet.")} else {window.location='twitterrific:///tweet?id='+x[1]};

Converted to bookmarklet: javascript:(function()%7Bvar%20x%20%3D%20%2Ftwitter.com%5C%2F.*%5C%2Fstatus%5C%2F(%5B0-9%5D%2B)%2F.exec(window.location.href)%3B%20if(x%20%3D%3D%20null)%20%7Balert(%22Doesn't%20look%20like%20this%20is%20a%20tweet.%22)%7D%20else%20%7Bwindow.location%3D'twitterrific%3A%2F%2F%2Ftweet%3Fid%3D'%2Bx%5B1%5D%7D%7D)()

Max Masnick
tag:tech-notes.maxmasnick.com,2013:Post/1204061 2017-11-08T18:09:55Z 2017-11-08T18:10:05Z Trim whitespace with AppleScript

This is directly from macscripter.net, but they have some encoding issues that I've fixed:

Max Masnick
tag:tech-notes.maxmasnick.com,2013:Post/1190796 2017-09-12T21:44:14Z 2017-09-12T21:44:14Z Make YouTube videos full screen on iPad ]]> Max Masnick tag:tech-notes.maxmasnick.com,2013:Post/1190258 2017-09-11T02:17:56Z 2017-09-11T02:25:27Z Keyboard Maestro macro to open .pickle file in IPython

I often want to view the contents of .pickle files on my computer. I like doing this in the IPython REPL, so I would manually open a new Terminal window, switch to my data science virtualenv, import pickle, and then load the .pickle file in question into a variable. Sounds like a prime target for automation, eh?

Here's a Keyboard Maestro macro that will take the selected .pickle file in Finder and open it up in IPython (inside iTerm2), assigning it to the variable x.

Here's what it looks like (the macro is triggered through LaunchBar with this custom action):

After the macro runs, I type in x to show the object in the Pickle file (in this case, it's just {"hello": "world"}.

Here's what the macro looks like in Keyboard Maestro:

Here's the code:

Note that this requires your Python virtualenv to be set up like this and you have to have a "data" virtualenv. If either of these things aren't true, you'll need to modify the shell commands in the AppleScript accordingly.

Max Masnick
tag:tech-notes.maxmasnick.com,2013:Post/1186058 2017-08-23T21:04:04Z 2017-08-23T21:04:04Z Add padding under each Jupyter cell

Put one of the following in a Jupyter notebook cell and run. If you make changes, clear cell contents, save, and refresh the browser.

All cells:

import IPython.core.display as di

$('<style>.cell { margin-bottom: 100px !important;}</style>').appendTo('head');
""", raw=True)

To add padding just after code cells:

import IPython.core.display as di

$('<style>.code_cell { margin-bottom: 100px !important;}</style>').appendTo('head');
""", raw=True)

To add padding just between code cells:

import IPython.core.display as di

$('<style>.code_cell+.code_cell { margin-top: 100px !important;}</style>').appendTo('head');
""", raw=True)
Max Masnick
tag:tech-notes.maxmasnick.com,2013:Post/1179092 2017-07-31T21:12:29Z 2017-07-31T21:12:29Z Show currently executing queries in MySQL


Max Masnick
tag:tech-notes.maxmasnick.com,2013:Post/1163180 2017-06-12T15:18:20Z 2017-06-12T15:18:34Z Fix broken camera on macOS without restarting

Sometimes the built-in camera on my Mac will stop working (no green light; no video). Restarting will fix it, but this appears to also work: sudo killall VDCAssistant

Max Masnick
tag:tech-notes.maxmasnick.com,2013:Post/1158719 2017-05-30T03:15:48Z 2017-10-14T13:42:20Z Disabling the startup chime on macOS Sierra

From How-To Geek:

Run sudo nvram SystemAudioVolume=%80 in the Terminal to disable the startup chime. Works like a charm on my late 2014 iMac.

To re-enable, run sudo nvram -d SystemAudioVolume (I didn't test this part).

Max Masnick
tag:tech-notes.maxmasnick.com,2013:Post/1153468 2017-05-12T11:12:34Z 2017-05-12T11:12:34Z macOS: Set audio balance to middle to correct drift with an AppleScript

On multiple Macs, I have had the left/right balance of my headphones randomly drift. Apple says this can be caused by changing the volume while the CPU is under load, which doesn't seem to be what is happening to me. In any case, it's annoying.

Here's an AppleScript that will automatically reset the sound balance to the middle for the current output device:

There's also a $5 app called Balance Lock that in theory will solve this problem – I haven't tested it.

Max Masnick
tag:tech-notes.maxmasnick.com,2013:Post/1152686 2017-05-09T11:34:46Z 2017-05-09T11:34:46Z Loading multiple MySQL result sets into Pandas DataFrames

Note: This could be done in a loop. I don't do this because I often have results set-specific code that I want to run (e.g. renaming variables).

Max Masnick
tag:tech-notes.maxmasnick.com,2013:Post/1150522 2017-04-30T20:21:17Z 2017-04-30T20:21:17Z Darkening gray text with ImageMagick

The following ImageMagick command will take an image with gray text (and a white background) and make the text black.

magick convert -level 80%,100%,1 in.png out.png

Max Masnick
tag:tech-notes.maxmasnick.com,2013:Post/1149147 2017-04-25T12:11:34Z 2017-04-25T12:11:34Z 2x2 tables in Jupyter/IPython notebooks

I've written some helper methods for quickly generating 2x2 tables (or contingency tables, cross tabulations, crosstabs) in Jupyter/IPython notebooks. This achieves the same thing, more or less, as Stata's tabulate twoway command.

The notebook below has the helper methods and examples of their output. I've added these to my ipython-setup file because I use them so frequently.

Max Masnick
tag:tech-notes.maxmasnick.com,2013:Post/1103156 2016-10-28T18:23:11Z 2016-10-28T18:23:11Z Hide all gifs with CSS
img[src*="gif"] {
    display: none;
Max Masnick
tag:tech-notes.maxmasnick.com,2013:Post/1085541 2016-09-01T04:20:02Z 2016-09-01T04:20:02Z Get SHA1 hash for every file in a folder on OS X

cd path/to/folder
ls * | xargs openssl sha1


Max Masnick
tag:tech-notes.maxmasnick.com,2013:Post/1081438 2016-08-15T20:01:18Z 2016-11-15T11:51:42Z Python: Get git hash for the last commit modifying the current folder
from os import path
p = path.dirname(path.abspath(__file__))
hash = subprocess.check_output(["git", "rev-list", "-1", "HEAD", "./"], cwd=p).strip()
Max Masnick
tag:tech-notes.maxmasnick.com,2013:Post/1078612 2016-08-03T22:39:01Z 2017-12-08T19:54:32Z Querying MySQL from Stata

Step 0: Install the ODBC driver

  1. Download and install the iODBC driver manager. The next step will fail if this isn't installed first.
  2. Download and install the ODBC driver.

Step 1: Set up ODBC driver

See these instructions. My ODBC configuration (~/.odbc.ini) looks like:

[ODBC Data Sources]
mysql = MySQL ODBC 5.3 ANSI Driver

Trace         = 0
TraceAutoStop = 0
TraceFile     = 
TraceLibrary  = 

Driver      = /usr/local/lib/libmyodbc5a.so
Description = desc here
SERVER      = localhost
PORT        = 3306
USER        = root
PASSWORD    = passwordhere
DATABASE    = databasehere

Make sure your driver location is correct. It could also be something like /usr/local/mysql-connector-odbc-5.3.7-macos10.12-x86-64bit/lib/libmyodbc5a.so.

Step 2: Make a ODBC call from Stata

For example:

set odbcdriver ansi
odbc list
// Option 1
odbc load, table("tablename") dsn("mysql") clear noquote
// Option 2
odbc load, exec("select * from tablename") dsn("mysql") clear noquote

Using a plugin is another option, but I haven't tried this.

Update: Loading in SQL from an external file

This allows you to do something like:

cd "/path/to/your/folder"
loadsql using your-sql.sql, dsn(mysql)

Max Masnick
tag:tech-notes.maxmasnick.com,2013:Post/1063375 2016-06-14T17:01:41Z 2018-03-01T17:24:53Z Literate Python setup with pweave and Atom

In the past I’ve used IPython/Jupyter notebooks for literate programming, but writing code in the browser is not a great experience and I was having terrible environment issues. I started looking at alternatives, and settled on trying out pweave. It’s the same idea as IPython, allowing me to intersperse code and output with prose, but rather than using the browser I can use a standard programming editor. (It also solves my environment problem.)

The setup for getting a pweave workflow that still has all the nice parts of an IPython notebook is a little involved, so here’s what I did:

  • Get the Atom editor (I generally use Sublime Text, but it can’t run Python inline)

  • Set up a virtualenv and pip install "ipython[notebook]" Pweave

  • Install the following Atom packages:
  • Make the following configuration changes:
    • Append to styles.less:

      // Hydrogen output - font size is too small  
      .hydrogen.output-bubble pre {  
        font-size: 16px !important;  
      // Hydrogen - hack for 2x images  
      .hydrogen.output-bubble .bubble-result-container img {  
        width: 50% !important  
    • Append to config.cson:

          commands: [  
              command: "expand-region:select-inside-back-ticks"  
              recursive: true  
    • Append to keymap.cson:

      '.platform-darwin atom-text-editor':  
        'cmd-enter': 'hydrogen:run',  
        'cmd-shift-space': 'expand-region:expand'
    • In the settings under Settings > Packages > Hydrogen:
      • Kernel Mappings (this enables support for .pmd files): {"pweave markdown": "Python 2"}

      • Startup Code:

        {"Python 2": "import matplotlib as matplotlib_import_only\nmatplotlib_import_only.use('Agg')\n%matplotlib inline\n%config InlineBackend.figure_format = 'retina'\npython=None"}

        This does a few hacky things:

        • import matplotlib as matplotlib_im ... rt_only.use('Agg'): fix for this issue with a bouncing rocketship dock icon
        • %matplotlib inline: display figures inside Atom rather than in a separate window
        • %config InlineBackend.figure_format = 'retina': turns on high-resolution figures, which are displayed by Atom as double-sized low-resolution figures without the hack in styles.less above
        • python=None: a hack to avoid an error when automatically selecting and running a block of Python code

Some of this configuration is necessary to just get hydrogen to run Python code.

The rest fixes a major problem with pweave: it’s easy to run one line of code, and it’s easy to run all the code in a file, but how do I run only one block of code? (This is equivalent to being able to running an entire cell in IPython with shift-enter.)

The solution is to use the expand-region plugin to select the current block of code, and the python=None hack to avoid an error when it selects the “python” in ```python.

Here’s what it looks like in action:

To convert the .pmd file to a .html that can be shared, simply run pweave -f md2html test.pmd. Here's what the output from the above example looks like.


  • Remember to open Atom from the command line after activating your virtualenv (see the "Usage" section here).
  • In order to get the pweave command to run with my virtualenv, I manually edited the shebang in /usr/local/bin/pweave to directly point to the Python binary in my virtualenv: #!/Users/max/.virtualenvs/data/bin/python
Max Masnick
tag:tech-notes.maxmasnick.com,2013:Post/1050816 2016-05-13T15:22:48Z 2016-05-13T15:22:48Z Reserved words lists in Ruby/Rails, Python, MySQL, and PostgreSQL ]]> Max Masnick