Somedays I write more bugs than code…

I posted recently that I had started on Bites of Py Exercises, and i’m glad to say I have finished a few more. Small wins are good!

Along the way i’ve discovered, thanks again to the Python Bytes podcast, a new way to see crashes in my scripts. Currently I am working slowly towards scraping my favorite wallpapers from wallhaven.cc and downloading them. But, as I mention in the title, I seem to be better at writing bugs than functional code.

When a script crashes in Python you get a traceback, which seems to be a backwards listing of the things that caused the crash. With practice I will get better at making sense of things like this:

Traceback (most recent call last):
   File "wff-selenium-no-login.py", line 6, in 
     from urllib import Request
 ImportError: cannot import name 'Request' from 'urllib'  NameError: name 'Request' is not defined
   File "wff-selenium-no-login.py", line 24, in 
     req = request(wallpaper, headers = {"User-Agent": "Mozilla/5.0"})
 TypeError: 'module' object is not callable

But thanks to that episode I learned about friendly_traceback, which gives me this output instead:

Python exception:
         TypeError: 'module' object is not callable
A TypeError is usually caused by trying to combine two incompatible types of objects, by calling a function with the wrong type of object,
or by tring to do an operation not allowed on a given type of object.

Execution stopped on line 24 of file 'wff-selenium-no-login.py'.
-->24:     req = request(wallpaper, headers = {"User-Agent": "Mozilla/5.0"})

request: <module 'urllib.request' from '/Users/davidr/...>

How is this better? Well.. it explains the error, points to the line I need to fix.. and also tells me the module I have issue with. Though I still don’t know what to do to fix it it makes me feel like I have a better handle on it.

Fun with SED!

(Found this sitting in my blog’s drafts folder.. only 11 years old but all of it still just as valid today!)

A couple of shell scripts for renaming files on the command line.

# Replaces JPG in any file with jpg 
for ii in * ; do ARG1=`echo $ii | sed 's/JPG/jpg/g'` ; mv $ii $ARG1 ; done

Stany’s renaming scripts:

#!/bin/bash
# Mass REname of english filenames
# relies on fixfilename regexp engine

PATH=$PATH:/Users/stany/bin
echo
for ii in * ; do ARG1=`echo $ii | fixfilename `   ; echo -n "." ; mv "$ii"  "$ARG1" ; done
echo
#!/bin/bash
# the fixfilename regexp engine

PATH=$PATH:/raid0/tools
sed 's@(@@g;s@)@@g;s/ /_/g;s/\,//g;s/\&/and/g;s/_-_/-/g;s/-_/-/g;s/\!//g;s/\;//g;s/\]//g;s/\[//g;s/%20/_/g' 

A combined version…

#!/bin/bash
for ii in * ; do ARG1=`echo $ii | sed 's@(@@g' | sed 's@)@@g' | sed 's/ /_/g' | sed 's/\,//g' | sed 's/\&/and/g' | sed 's/_-_/-/g' | sed 's/-_/-/g' | sed 's/\!//g' |  sed s/\;//g | sed 's/\]//g' |  sed 's/\[//g' | sed 's/%20/_/g'  `  ; echo -n "." ; mv "$ii"  "$ARG1" ; done
echo

This script will remove the first 4 characters of a filename:

for ii in * ; do FOO=`echo $ii | sed 's/^....//g'`; echo mv \"$ii\" \"$FOO\" ; done

This will echo what it actually does, and place quotes in front and after each filename. In the for ii in * bit you can adjust the regex to match the files you need. So for ii in *.txt will match all the files ending in .txt

Remove the echo to run it, or pipe into shell: | sh

Looking up Mac specs..

Did I mention I love TextExpander? Yeah.. so, to make a long story short: clients ask me questions about their computers, upgrades, lifespans, etc. I don’t normally remember all the details of their Macs so I get them to send me the Serial Number (Open the Apple menu, click About This Mac and it should be right there.)

Once you have it you can go by Apple’s support site and look it up… but that takes too long.

Make a new TextExpander snippet with Applescript as the content type:
property theURL : ""
set theURL to "http://support.apple.com/specs/#" & (the clipboard)
do shell script "open " & theURL

Then you just copy the serial number, and anywhere you can type use !specs to invoke it and up pops open Apple spec page a few seconds later.

Opening a pile of urls all at once — updated version!

A year or so ago I wrote a post on how to use xargs to open a bunch of urls that were in your clipboard. But it turns out that in newer versions of OS X something broke, deliberately or otherwise, and that method no longer works. Well, it works fine, it’s just *too* fast. So today I needed to check about a hundred urls.. and so it was time to fix that script. I’ve been slowly working on learning Python, so I decided to use that.. and this is what I ended up with:

#! /usr/bin/python
import webbrowser
import pyperclip
import time
url_list = pyperclip.paste()
clean_list = url_list.splitlines(False)
for x in clean_list:

    webbrowser.open(x)
    time.sleep(.5)

It only took me about an hour 😉

What does it do? It grabs the clipboard, splits each line inside the clipboard at the return character, and then there is a loop which tells the browser to open the url .. wait a half second and then do it again.

I’d like to figure out how to grab the clipboard and clean it in one line.. but that’s for another day!

Back to work..

How to mount the Windows partition of a hybrid DVD

A client of mine has an older Lenovo laptop with a defective DVD drive. He’s saving for a MacBook Air rather than spend money fixing it! I downloaded the installer for his new Fujitsu ScanSnap so he could get up and running right away. But the DVD has goodies that you can not download, so I offered to bring it back home and copy the installers to a USB stick. When I put the DVD in I only get the Mac partition. So here’s how I worked around it:

You need to have a mount point for the Windows partition, on the Mac one gets created in /Volumes when you mount something, we need to make one, so pop open your Terminal and do:

mkdir /Volumes/windows

This creates a directory named “windows”. You can name it whatever you want.

Now you need to find the device name of the DVD:

diskutil list

and, since the DVD is in the drive, you’ll see it come up as a device, and some partitions. In my case it was:

/dev/disk1
#: TYPE NAME SIZE IDENTIFIER
0: Apple_partition_scheme *3.3 GB disk1
1: Apple_partition_map 17.9 KB disk1s1
2: Apple_HFS ScanSnap 943.7 MB disk1s2

To mount the Windows side of the CD:

sudo mount -t cd9660 -r /dev/disk1 /Volumes/windows

sudo to prove we are an admin (SuperUser DO), and the mount command with options to mount 9660 format, the device and the path to mount it at.

It showed up as expected, and then I copied the installers I needed. You can try dismounting it in the Finder, but that will not work, you need to unmount it like this:

sudo umount /Volumes/windows

Note that it is umount not un-mount.

Then go and delete the directory, in the Finder or on the command line:

rmdir /Volumes/windows

After that, you can eject the CD normally, or if you tried from the Finder and can no longer see it, do it from the command line:

diskutil eject /dev/disk1

No I did not figure this all out on my own, I used an article from the codeweavers support wiki. Thanks!

Controlling iTunes from the command line

I had a little fun the other day, making a script that would pause iTunes, from the command line. In the end I made ones to pause, play, and go forward a track.

All of them use a slightly modified version of a line of Applescript:

tell application “iTunes” to play

You can also tell it “to next track, to pause, to stop, to previous track”, which all work as expected.

To get it to work on the command line you’ll need to turn it into a script, which is a plain text file with some command line options in it. To get Applescript to work on the command line we need to use osascript, with the “-e” option.

Here’s what you should have in your file:

#!/bin/bash
osascript -e “Tell application “iTunes” to pause”

Note the the quotes and slashes? You need to wrap the Applescript command in quotes, and since you have quotes in the middle of it, you need to escape them using the slashes so the whole applescript is parsed.

Next step is to save the script to somewhere useful. In my case I have set my command line environment to check for scripts in ~/bin/ , so I saved it there as ‘pause’. After that you will need to make it an executable, so pop into the terminal and do “chmod +x ~/path-to-your-file/pause”, at which point you run it.

Go play something in iTunes, and then go over to the Terminal and type “pause” and hit enter. If your script is in your environment path then iTunes just paused…

Here are the other scripts I used, just to make your life easier 😉

#!/bin/bash
osascript -e “Tell application “iTunes” to play”

#!/bin/bash
osascript -e “Tell application “iTunes” to next track”

Feedback is appreciated!