Ben Crowder / Blog

Blog: #python

24 posts / tag feed / about the blog / archive / tags

epubdiff

I’ve released epubdiff, a Python script for diffing EPUBs.


Reply via email or office hours

Mozilla just announced their Pyodide project, built with WebAssembly and emscripten:

Pyodide gives you a full, standard Python interpreter that runs entirely in the browser, with full access to the browser’s Web APIs.

WebAssembly has a lot of potential. I’m excited to see where it goes.


Reply via email or office hours

Scrub

Just released Scrub, that Python script for bleeping profanity out of EPUBs that I mentioned a couple months ago.


Reply via email or office hours

Good post on ownership in Rust, using Python as an example.


Reply via email or office hours

Came across Joel Grus’s I Don’t Like Notebooks slides on the downsides of Jupyter notebooks. I don’t really use Jupyter (other than when a class I recently took required it), but these are good points.


Reply via email or office hours

Came across a great tip on Python multiline strings using textwrap.dedent (so you don’t have to dedent everything in your code).


Reply via email or office hours

Book of Mormon study edition 2.0

I’m pleased to announce version 2.0 of my Book of Mormon study edition.

study-edition-eng-bofm-00.jpg

This version now uses the licensed text of the scriptures from the Church, which means I’m finally able to make editions in other languages. To start out, we’ve got French, German, Italian, Portuguese, and of course Spanish.

study-edition-spa-bofm-02.png

To make it easier to create versions of the study edition in other languages, I started over from scratch, using a set of Python scripts to pull the text from the files the Church sent me, then generate a LaTeX document that gets turned into the PDF. It’s a really nice workflow.

study-edition-eng-bofm-01.png

Over the next month or so I’ll be revising several of my other scriptures projects (reader’s edition, Words of the Prophets, etc.) to use the licensed text, with a similar Python-based workflow to make updates easier.

Also, if you’re interested in a study edition in a new language, let me know.


Reply via email or office hours

Bubbles

Playing around:

bubbles.jpg

I wrote the circle chording code on my phone in Pythonista, then ported it to PlotDevice, fleshed it out, and textured it in Photoshop.


Reply via email or office hours

I’ve renamed inkpdf to Press (as in printing press).

I reached the point where creating the PDF manually is no longer feasible, so I’ve been working on getting Press to a point where I can implement the PDF generation. The basic structure is in place, sans the PDF part. (That’s next.)

Here’s what a Press script looks like right now:

from press import Press

p = Press('output.pdf', width=6*Press.INCH, height=11*Press.INCH,
          margin=1*Press.INCH)

# Horizontal borders at top and bottom of page
p.stroke('#000')
p.pen(1.0)
p.line(p.page_min_x, p.page_min_y, p.page_max_x, p.page_min_y)
p.line(p.page_max_x, p.page_min_y, p.page_max_x, p.page_max_y)

# Page 2
p.page(2)
p.layer('base')
p.stroke(rgb=(1, 0, 0))
p.line(150, 150, 300, 300)
p.layer('fg')
p.stroke(hsl=(0, 0.5, 0.8))
p.line(300, 300, 450, 150)

# Go back and add another line to page 1
p.page(1)
p.stroke('#025')
p.line(p.page_min_x, p.page_min_y, p.page_min_x, p.page_max_y)

p.save() # this doesn't work yet

You can also do something like this:

with Press('output2.pdf', size=Press.LETTER,
           margin=(0.5*Press.INCH, 1.0*Press.INCH),
           inner_margin=0.5*Press.INCH,
           outer_margin=1.25*Press.INCH,
           bleed=.125*Press.INCH) as p:
    p.line(50, 50, 250, 50)
    # And so on

(Context manager, inner/outer margin, bleed, built-in paper sizes.)

Up next: adding more primitives, designing the font selection mechanism, getting it to generate an actual PDF, embedding fonts, using arbitrary Unicode code points, integrating HarfBuzz, etc.


Reply via email or office hours

Lifter is “a lightweight query engine for Python iterables.” Looks nice. One of their examples:

# vanilla Python
results = [
    user for user in users
    if user['age'] == 26 and user['is_active']
]

# lifter
results = manager.filter(User.age == 26, User.is_active == True)

Reply via email or office hours