Search Your Library from Pythonista

It's been far too long since I've posted any code, so here's something I was fiddling around with this weekend.

I have a large library of real, paper books. I keep them catalogued in Delicious Library, which sadly has no mobile app (anymore). This makes it difficult to figure out if I already own a book when I don't have access to my Mac. I used to keep a parallel database in Bento because it had iOS versions. But now Bento is going away and I need yet another solution.

Since Delicious Library has (frustratingly non-scriptable) export functionality, I can get a nice flat text file with all of my books. I can keep that file in Dropbox and search it using the following script in Pythonista. I've chosen to export only the author and title fields in a tab delimited format1, but there are a plethora of other fields and formats available to you.

import re
import os
import sys
import webbrowser
from dropboxlogin import get_client

client = get_client()

f = client.get_file('/path/to/Library.txt')
books = f.read().split('\n')

template = '.*(%s).*'
query = sys.argv[1]

# I ganked this from http://www.cademuir.eu/blog/2011/10/20/python-searching-for-a-string-within-a-list-list-comprehension/
regex = re.compile((template % query), re.IGNORECASE)
results = [m.group(0) for l in books for m in [regex.search(l)] if m]

if results:
    content = """
        <table border=1>
        <tr>
        <th>Author</th>
        <th>Title</th>
        </tr>
        {rows}
        </table>
        """.format(rows = "\n".join(['<tr>\n\t<td>{0}</td>\n\t<td>{1}</td>\n</tr>'.format(*i.split('\t')) for i in results]))
else:
    content = """
        <p>No results found</p>
        """

html = """
<html>
<head>
    <title>Search Results</title>
</head>
<body>
{content}
</body>
</html>
""".format(content=content)

with open("results.html", 'w') as f:
    f.write(html)

pth = "file:///" + os.path.join(os.path.dirname(os.path.abspath(__file__)), "results.html")

webbrowser.open(pth)

I know it looks like a hot mess of string formats and list comprehensions, but I suspect that it's the most efficient way to go.

This version assumes it's running from something like Launch Center Pro or Drafts. If you wanted to run it directly from Pythonista, change the query variable assignment in line 14 to something like query = console.alert("Enter search query"). And don't forget to import console if you do that. Obviously you'll want to change the path in line 9 in any case.

The gistified version is here.


  1. Why tabs instead of commas? I think it's prettier to look at a tab delimited file in the Finder or a terminal. 

Share on App.net

Comments !

++useful

elsewhere