Friday, September 22, 2017

The Republicans’ Latest Epiphany: Punt

The Graham-Cassidy bill, so named because it was primarily authored by Senators Lindsay Graham (Republican, South Carolina) and Bill Cassidy (Republican, Louisiana), is the latest attempt on the part of the Republican Party to “repeal and replace” the Affordable Care Act, also known as Obamacare. The lynchpin of this latest plan is something that undoubtedly seemed like a masterstroke to Senators Graham and Cassidy: the plan delegates almost everything healthcare related to the states.

Why would Republicans gravitate to such a plan? Several reasons. First, it feels ideologically pure to Republicans. Although they rarely govern this way in practice, Republicans often tout their belief that the states govern better than the Federal government.1 Second, it lets them keep their promise to their base to repeal Obamacare while deflecting responsibility for doing so. Obamacare is now mostly viewed favorably by Americans while GOP efforts to repeal it are deeply unpopular. Nevertheless, repealing Obamacare remains a high priority for the Republican base and donors. Finally, it alleviates the need for Congressional Republicans to work out the details before their window for passing a bill through the Senate with only 51 votes closes on September 30.2

Of course, all of this is nonsense. The states generally don’t govern all that well and have only rarely acted as the “laboratories of democracy” that Republicans so often talk about. In fact, most state legislatures are part time, leaving state legislators precious little time to adequate study and debate a topic as complex as health care.3 The states had years to enact health care legislation before the Affordable Care Act passed and only one ever did: Massachusetts.

Most importantly, anyone who tells you that this bill will increase coverage, decrease premiums, or protect people who have pre-existing conditions is lying. This bill turns all of those decisions over to the states and many states will not be up to the challenge. And oddly enough, once again, it’s a comedian who is the voice of reason in this debate:


  1. “I believe in state’s rights;” was the key phrase in a controversial speech Ronald Reagan gave at the Neshoba County Fair in 1980

  2. Normally, legislation in the Senate is subject to the filibuster. Any Senator can, under the standing rules of the Senate, prolong debate on any measure indefinitely and when that happens, a ⅗ majority (60 votes) is required to end debate and proceed to a vote. But the Senate has a special filibuster-proof process for budget bills called reconciliation and earlier this year a bill passed that qualified the healthcare repeal efforts for the reconciliation process. But the Senate parliamentarian has ruled that that qualification ends with the current fiscal year, on September 30. 

  3. Utah’s legislature, for example, meets for only 45 days a year. Imaging trying to pass a true health care bill at same time you are considering hundreds of other bills in only 45 days! 


Monday, December 5, 2016

“Democracy, Meh?” ↦

The New York Times recently reported on a troubling statistic:

Across numerous countries, including Australia, Britain, the Netherlands, New Zealand, Sweden and the United States, the percentage of people who say it is “essential” to live in a democracy has plummeted, and it is especially low among younger generations.

FiveThirtyEight posted a quick take on the survey that prompted that article:

First, the bad news: That data is legitimate, and it fits with research other pollsters have done on the millennial generation — loosely defined as everybody born from 1980 to 1997. …

That said, this isn’t exactly the same thing as millennials not liking democracy or clamoring for a dictator, Taylor said[.] … “By any metric, government has performed badly” over the last 20 years, he told me. Millennials have come of age in a time when our democratic government has been characterized by gridlock, partisanship, ineffectiveness and resistance to change.

20 years of gridlock is too much. That’s long enough to know that occasionally voting in different Republicans and different Democrats is not going to fix things, as that has happened over those years. We need more. We need to change how we vote, not just who we vote for.


Monday, December 5, 2016

“Political Moneyball: America’s Unfair Elections and the Republicans’ Art of Winning Them” ↦

Jason Kottke shares his thoughts on America’s electoral system (and some great C. G. P. Grey election videos):

More than anything for me, this is the story of politics in America right now: a shrinking and increasingly extremist underdog party has punched above its weight over the past few election cycles by methodically exploiting the weaknesses in our current political system. Gerrymandering, voter suppression, the passing of voter ID laws, and spreading propaganda via conservative and social media channels has led to disproportionate Republican representation in many areas of the country which they then use to gerrymander and pass more restrictive voter ID laws.

Exactly right. Take my home state of Utah as an example. Utah has 4 seats in the federal House of Representatives. Currently, all 4 of those seats are held by Republicans. Utah, while (in)famous for being a “deep red” state, is not 100% Republican. Based on the results of 2016’s statewide elections, Utah is “only” 64%1 Republican. Therefore, at least one of Utah’s seats should be held by a another party, if elections were to be actually representative of the will of the people.

If you, like me, are concerned about where our country is headed after this year’s election, working to defeat Trump in 2020 is simply not enough. Particular candidates like Trump are symptoms of the problem, not the cause. We need to fix America’s democracy at a much more fundamental level than just voting out a specific, distasteful demagogue.


  1. To arrive at the 64% figure, I averaged the percentage of Republican votes for all of the 4 Utah statewide offices up for election in 2016: Governor (66.75%), Attorney General (65.41%), Auditor (63.23%), and Treasurer (61.23%). As of Monday, December 5, 2016, the results have not been certified as final but I don’t think they will change much. I intentionally did not include the presidential race, as Evan McMullin’s independent run split Utah’s Republican votes for president. 


Monday, October 17, 2016

Donald Trump Fact Checked in the Style of Arrested Development

So good.


Sunday, October 16, 2016

Regular Expression Capture Groups in Swift 3 on Linux

I recently decided to have a go at using Swift. I’ve dabbled with Swift before, run through the odd tutorial but this time I wanted to actually use Swift to accomplish something. I tend to internalize programming languages far better that way. And since Swift is open source and touted to be a contender for a server-side language, I wanted to try Swift on Linux.

As I got going, I found I needed to use regular expression capture groups to find some parts of a string and then return an array of those parts. In most modern programming languages, this would be a perfectly straightforward exercise. Nearly all programming languages these days include a regular expression engine of some sort in their standard libraries and a little Googling will tell you all you need to know about the peculiarities of that language’s regular expression syntax and the APIs for using it. Swift, though, is a bit different.

Swift’s own standard library — by which I mean the included objects and functions that are Swift from the ground up and are not derived from Objective-C predecessors — is actually quite small. It consists mostly of built-in types like Arrays and Strings. The rest of the standard library, including the regular expression engine, actually consists of bridges to Objective-C objects. As far as I can tell, bridging to Objective-C objects works just fine for the most part; Swift was designed, after all, to easily interoperate with Objective-C. But there are corner cases where frustration flourishes.

To get started, I found a Stack Overflow answer which proposed the following Swift 3/Xcode 8 compatible function for getting the matching substrings:

func matches(for regex: String, in text: String) -> [String] {
    do {
        let regex = try NSRegularExpression(pattern: regex)
        let nsString = text as NSString
        let results = regex.matches(in: text, range: NSRange(location: 0, length: nsString.length))
        return results.map { nsString.substring(with: $0.range) }
    } catch let error {
        print("invalid regex: \(error.localizedDescription)")
        return []
    }
}

The main idea here is to cast the Swift String into an Objective-C NSString. NSString could then give me the NSRange objects that need to be passed to NSRegularExpression. This code does indeed compile and execute correctly on m⁠a⁠c⁠O⁠S using Xcode 8.

On Linux, however, I immediately ran into problems. The first is that Swift would absolutely not allow me to use the name NSRegularExpression; I had to use the munged name RegularExpression. (The idea seems to be that if there are Swift-native equivalents — as String is a Swift-native equivalent to NSString — then you can use the NS prefix to still refer to the Objective-C version. If there is not a Swift-native equivalent — as is the case with NSRegularExpression — then you must always remove the NS prefix.)

func matches(for regex: String, in text: String) -> [String] {
    do {
        let regex = try RegularExpression(pattern: regex)
        let nsString = text as NSString
        let results = regex.matches(in: text, range: NSRange(location: 0, length: nsString.length))
        return results.map { nsString.substring(with: $0.range) }
    } catch let error {
        print("invalid regex: \(error.localizedDescription)")
        return []
    }
}

Once that was fixed, I got errors about missing arguments for RegularExpression and its matches method. Adding the options argument to both calls was easy though it remains curious that they would be required on Linux but not on macOS.

func matches(for regex: String, in text: String) -> [String] {
    do {
        let regex = try RegularExpression(pattern: regex, options: [])
        let nsString = text as NSString
        let results = regex.matches(in: text, options: [], range: NSRange(location: 0, length: nsString.length))
        return results.map { nsString.substring(with: $0.range) }
    } catch let error {
        print("invalid regex: \(error.localizedDescription)")
        return []
    }
}

The more vexing problem was that I got an error regarding the conversion of String to NSString: “cannot convert value of type ‘String’ to type ‘NSString’ in coercion”. Initially, I assumed that NSString was simply not available on Linux and I went down quite a rabbit hole of trying to get an NSRange from String so that I could avoid using NSString altogether. It turns out, however, that doing so was unnecessary. NSString is indeed available in Swift on Linux and although the type coercion mysteriously doesn’t work, instantiating an NSString manually does:

func matches(for regex: String, in text: String) -> [String] {
    do {
        let regex = try RegularExpression(pattern: regex, options: [])
        let nsString = NSString(string: text)
        let results = regex.matches(in: text, options: [], range: NSRange(location: 0, length: nsString.length))
        return results.map { nsString.substring(with: $0.range) }
    } catch let error {
        print("invalid regex: \(error.localizedDescription)")
        return []
    }
}

I’m not sure why these differences, in particular, exist between compilation on the two platforms. The Linux version of the code does compile and run on macOS with the sole exception of having to swap NSRegularExpression for RegularExpression.


Friday, August 19, 2016

“Is Donald Trump Actually Trying to Win?” ↦

John Gruber makes the case that Donald Trump isn’t actually trying to win the election for President:

Nate Silver, “Trump Is Doubling Down on a Losing Strategy”:

So it’s not surprising that Trump has undertaken a major shakeup of his campaign, hiring Bannon and promoting the pollster Kellyanne Conway. Campaign Chairman Paul Manafort has effectively been demoted. But rather than make a much-expected “pivot” toward general election voters — as Manafort had reportedly been pushing for — the new plan is to “let Trump be Trump,” doubling down on the strategies that Trump used to win the nomination, including an emphasis on nationalism, populism and “brutal fights with Clinton”.

[…]

In short, Trump isn’t trying to appeal to more people, which is how you win elections. He’s trying to appeal more to the people who already support him. That’s how you might build an audience for an “alt-right” media company.

Maybe. There’s another perfectly plausible explanation, however: Trump, and the advisors he recently promoted, genuinely buy into the idea that “let Trump be Trump” is the strategy that won the primaries and is therefore their best chance for the general election. That Trump will no longer have to chafe under the restraints that Manafort wanted to put on him is the icing on the cake. After all, so this line of thinking goes, Manafort was in charge for 2 months and Trump’s numbers went down, not up.

A key piece of evidence that Gruber cites is this quote from a former Trump staffer, Stephanie Cekielski:

Even Trump’s most trusted advisors didn’t expect him to fare this well.

Almost a year ago, recruited for my public relations and public policy expertise, I sat in Trump Tower being told that the goal was to get The Donald to poll in double digits and come in second in delegate count. That was it.

The Trump camp would have been satisfied to see him polling at 12% and taking second place to a candidate who might hold 50%. His candidacy was a protest candidacy.

I’ll just point out that this expectation — of Trump coming in second in the primaries — came from Trump’s advisors, not Trump. It’s likely that, a year ago, Trump’s advisors were just as perplexed by his candidacy as the rest of us were. And although Ms. Cekielski firmly believes that Trump got into the race not expecting to win (an opinion shared by Michael Moore, claiming some unspecified insider knowledge1), she points out what is perhaps Trump’s most salient personality trait:

The Donald does not fail. The Donald does not have any weakness.

As Nate Silver points out, Donald Trump is doubling down on a losing strategy. Maybe that’s because he’s sabotaging a campaign that he never actually wanted to win. Or maybe the truth is as obvious as Mr. Trump’s hairpiece: Donald Trump is a self-absorbed narcissist who actually believes that the best way to win the election is to put his personality on full display instead of trying to smooth it over.

Let’s not forget Hanlon’s2 razor: “Never assume malice when stupidity will suffice.”


  1. It’s difficult to imagine a scenario in which Michael Moore, the second most vilified liberal after Hillary Clinton, would become the confidant of a Trump and/or Republican insider. Not impossible but very difficult. 

  2. Or is it Heinlein’s razor


Wednesday, August 17, 2016

Django Print SQL Middleware

Django’s object-relational mapper (ORM) is perhaps that framework’s best feature. It’s both easy to use and very powerful. Nevertheless, I believe it’s important to keep an eye on the queries that it generates. It’s often easy to miss cases where you’ve unintentionally triggered a new query when accessing a foreign key or when duplicate queries are being generated.

The Django Debug Toolbar is probably the most widely used tool for peering into Django’s database activity. Personally, though, I’ve always found that it tends to get in the way of the UI that I’m developing. I’ve long preferred to see the SQL output to the console instead. I used to use Django devserver’s SQLRealTimeModule for that purpose but devserver has been running into compatibility problems with recent versions of Django. So, I’ve written my own middleware based on the devserver module. I recently updated it to work with Django 1.10’s new style of middleware, so I thought I’d share it:

import re
from decimal import Decimal

import sqlparse
from django.db import connection

_sql_fields_re = re.compile(r'SELECT .*? FROM')
_sql_aggregates_re = re.compile(r'SELECT .*?(COUNT|SUM|AVERAGE|MIN|MAX).*? FROM')


def truncate_sql(sql, aggregates=True):
    if not aggregates and _sql_aggregates_re.match(sql):
        return sql
    return _sql_fields_re.sub('SELECT … FROM', sql)


def printsql_middleware(get_response):
    def middleware(request):
        response = get_response(request)
        num_queries = 0
        time = Decimal('0.0000')
        for query in connection.queries:
            num_queries += 1
            time += Decimal(query['time'])
            sql = truncate_sql(query['sql'], aggregates=False)
            formatted_sql = sqlparse.format(sql, reindent=True)
            for index, line in enumerate(formatted_sql.split('\n')):
                if index == 0:
                    print('[SQL] {}'.format(line))
                else:
                    print('      {}'.format(line))
        deduped = set([q['sql'] for q in connection.queries])
        print('[SQL] {} queries, {} duplicates. {} seconds.'.format(num_queries, num_queries - len(deduped), time))
        return response
    return middleware

Of course, you should only use this middleware in development and never in production. It requires SQLParse to be installed.


Tuesday, August 9, 2016

“PyPy Gets Funding From Mozilla for Python 3.5 Support” ↦

Mozilla recently decided to award $200,000 to PyPy as part of its Mozilla Open Source Support (MOSS) initiative. This money will be used to implement the Python 3.5 features in PyPy. Within the next year, we plan to use the money to pay four core PyPy developers half-time to work on the missing features and on some of the big performance and cpyext issues.

This is good news indeed. I’ve been using Python 3.x in all new projects for some time now. For a while, I was using pypy3 in those projects until my most frequently used library, Django, dropped support for Python 3.3 (which is the version that pypy3 currently targets). I’m looking forward to regaining the performance advantages of using PyPy.

Kudos to Mozilla for supporting open source software development. Hopefully other corporations and organizations will follow their lead.


Friday, August 5, 2016

First Private Mission to the Moon ↦

The first company to apply for a commercial space mission beyond Earth orbit has just received approval from the federal government. As part of the Google Lunar X Prize competition, Moon Express intends to launch a small, single-stage spacecraft to land on the Moon by the end of 2017.

I’m very excited to see if anyone can claim the Lunar X Prize before the end-of-2017 deadline.


Friday, August 5, 2016

Frequent Password Changes Are a Bad Idea ↦

Cranor eventually approached the chief information officer and the chief information security officer for the FTC and told them what a growing number of security experts have come to believe. Frequent password changes do little to improve security and very possibly make security worse by encouraging the use of passwords that are more susceptible to cracking.

[…]

Over the past few years, organizations including the National Institute of Standards and Technology in the US and UK government agency CESG have also concluded that mandated password changes are often ineffective or counterproductive.

Bingo.