This Is Not a Pandemic

Published at 15:29 on 13 May 2026

It is scary that hantavirus is transmitting from human to human, and not via intermediate rodent hosts as is typical. But it is not a new development. The strain detected occurs in South America, where it transmits from human to human from time to time. Such it has been for a long time, and it hasn’t turned into a global (or even a regional) pandemic. The cruise began in Argentina, so it is obvious how its passengers originally became exposed. It spread like it did because a cruise ship concentrates a lot of people into a small space.

When the experts claim this is not going to turn into a pandemic, they are correct.

Evaluating Avalonia

Published at 09:49 on 13 May 2026

The suckiness that is the Java build environment finally got to me. That corrupt JAR file (the second time this has happened to me) was the final straw. I should not have to debug common build tools and the files they make. They should just work. The only bugs I should routinely battle with are the ones I just wrote in my own code. That is quite enough work, thank you very much.

So, despite Java in many ways being the best way to write a portable graphical application for the desktop, those JCA’s just are too much. The final straw had broken the camel’s back.

I had sort of been biased against Avalonia since learning that it focuses on pixel-for-pixel consistency between platforms (something I believe is a big mistake for desktop application programming). Then again, ASP.NET Core is so much better than any Python alternative web framework and Avalonia uses a similar code-behind model. Maybe the pixel-for-pixel compatibility doesn’t result in something that bad after all?

Executive summary: The rendering is better than I thought, but it doesn’t matter. There are enough other reasons not to use Avalonia.

File dialogs. In Swing (Java), Qt, and wxWidgets, one can customize these by adding extra controls. In Avalonia, you get the standard file dialog and that is it, no provision for customization. Want to ask for more parameters? Pop up a second dialog. The problem is, that is often a losing user experience; many load and save operations just naturally lend themselves to a need for a little extra information. Better to handle it all in one step, unless one is asking for a lot of extra information (and one usually is not).

File filters in dialogs. In Java and wxWidgets, you filter files by extension. In Qt, you filter by extension or MIME type. In Avalonia, you filter by extension on Windows and Linux. Linux also offers the option of filtering by MIME type. On the Mac, neither of the above work; you must filter on this wonky thing called an “Apple uniform identifier type.” Hello? The whole point of a cross-platform framework is to smooth this sort of stuff out! I shouldn’t have to deal with any weird Apple-specific stuff like this at all; it should just be MIME types and/or extensions everywhere. So stupid and annoying.

Data types in the clipboard. On most frameworks (Java Swing and AWT, Qt, wxWidgets) these are normalized from system-to-system. On Avalonia, the story is similar to file frameworks: one way for Linux and Windows, another way (those “Apple uniform identifier types” again) on Macs.

XAML. This is the declarative, layout-describing language that one codes behind. Unfortunately, unlike Razor templates in ASP.NET (which are powerful and have access to basically all C# control structures), XAML is pretty weak-sauce. It’s a garden-variety XML schema, with little or no provision for imperative coding. This is a pretty big problem, as cross-platform GUI programming often necessitates imperative coding. Consider pull-down menus; the Mac organizes them quite differently than do Windows or Linux. So a user-friendly app will include conditional logic and adapt itself accordingly. This is not exactly easy in XAML. You have to use some brand-new (and poorly-documented) features, some of which have some truly obnoxious misfeatures. The end result ends up being a lot more verbose and repetitive than it needs to be.

MVVM. Avalonia rams the model-view-view-model paradigm down your throat. It’s possible to resist this, but you have to work at it. MVVM was an effort to manage complexity in very large and complex programs. Not all programs are very large and complex (and fewer programs should be), so not all programs need MVVM. Even the inventor of MVVM openly admits this. Worse, the flavour of MVVM that Avalonia pushes is cartoonishly rigid, formulaic, and doctrinaire. Every view gets its own separate view model, even though it often makes more sense to share a view model amongst cooperating views. Even worse yet, by pushing something that makes sense for the largest programs, one pushes the mindset that computer programs should by default be large and complex. This mindset is positively harmful, as it leads to feature bloat.

The documentation. XAML is all standard controls classes under the hood, so one doesn’t have to use it. One can just use those controls classes directly, in C#. Then one gets the full suite of comprehensive imperative programming features C# has. Unfortunately, the documentation on how to do this is extremely incomplete. It’s mostly focused on how to do things in XAML. What documentation there is tends to be something of a mess. Complex classes, with many dozens of properties and methods, and nothing in alphabetical order. Why? Just why? There is simply no excuse for this lack of organization.

The choice of what programming language to use is often dictated by frameworks and libraries, and not the core features of the language itself. So it is here. Everything other than Avalonia in C# is generally worse than Avalonia. So C# simply doesn’t make sense for this project.

It is the exact converse of the situation with back-end Web programming. This time, it is Python that has clearly the best framework.

Why? Culture. Group identification. Avalonia was written by people that came out of the .NET world and wanted to make .NET applications more portable. It was strongly patterned after Windows frameworks like WPF. User-friendly GUI programs have never precisely been Microsoft’s strongest suit; Windows is rightly regarded as inferior to the Mac when it comes to user friendliness. It just turns out that that externally-visible awkwardness is there in no small part due to internal awkwardness bubbling up to the surface. And because the Windows universe is really big, most of those in it are astoundingly ignorant of what other universes have done.

When it came to Web servers, Microsoft had been left behind. They had to do a good job on ASP.NET, else nobody would switch over from the various open source frameworks that had already dominated the landscape. When it comes to the desktop, the exact opposite was the case. Complacency tends to produce inferior outcomes.

That said, I still might use Avalonia someday. If, that is, I ever have occasion to develop another smartphone app. I would want it to be portable, and the main alternatives to Avalonia for such things are Electron and Qt. The former is Javascript-based, and the way Javascript so badly botched modules and imports is reason enough to eschew the language. Qt is, well, Qt, and I will get into the specifics of that particular flavour of awfulness soon.

Portable GUI Frameworks

Published at 22:01 on 11 May 2026

I’ve been experimenting with them, because I have a need to rewrite a tool I use from Kotlin into some other programming language. Not because of any real defects in Kotlin (despite its proximity to the Java world and its associated JCA’s, this is not a show-stopper).

No, the problem is that I need to read HEIC files, and there is no good, easy way to do this in Kotlin, because there are simply no good, open-source, comprehensive, general-purpose imaging processing libraries available for the JVM. There are limited libraries that do not support HEIC nor the large size of the HEIC images I wish to read (such as the built-in stuff in the standard Java class library). There are esoteric libraries like ImageJ that support all sorts of oddball image formats used in the microscopy and health care fields, but not HEIC. There is no shortage of libraries that are abandonware and haven’t had an update in a decade or more.

By contrast, C# has Magick.NET and Python has Pillow, both of which do what I want. So I have been looking into GUI frameworks for those languages. Lets just say there are a lot of bad ones and leave it at that for now. I will post some details on the badness later (some of it is pretty mind-blowingly bad).

Suffice it to say that at this point I am reasonably sure wxPython will suit my needs, and it took a disgustingly long period of trial-and-error to get to that conclusion.

The Ebook Hard Sell

Published at 09:00 on 23 April 2026

This, I think, is how the capitalists are going to force more widespread adoption of ebooks (which are otherwise a questionable value proposition):

They will, in other words, deliberately under-produce (or, better yet, not produce at all) real paper books, books that give one the full right of ownership. Then, when customers understandably shy away from buying artificially scarce items at artificially inflated prices, announce that “the market has spoken” and there is no longer significant “customer interest” in traditional paper books.

The Trump-Vatican Spat

Published at 20:05 on 17 April 2026

Trump is ending up on the wrong side of the Catholic Church hierarchy. Pope Leo XIV, the first American pope, has issued multiple thinly-veiled criticisms of the Trump Regime’s policies, and Trump is increasingly unhappy (and vocally so) about it.

In the last 50 years, the track record of regimes that ended up prominently on the Vatican’s wrong side is, let us say, not precisely great. Most famously, of course, is the Soviet regime and its system of satellite states in eastern and central Europe. It all started with the emergence of Solidarność within about a year of the new Pope’s return visit to his homeland.

Pope John Paul II (and the Catholic Church in general) are cast in the popular view as figures of the Right for their role in undermining a nominally socialist system, and for their traditionalist views on the role and rights of women, the family, and homosexuality. It’s not so simple. Yes, those views exist, no doubt about it.

But Catholic social teaching has also long been critical of unbridled free-market capitalism. This goes way back. Literally back to Jesus Christ. The Gospels are full of messages of sympathy for the poor, the foreigner, and the less fortunate in general. That same “conservative” John Paul II wrote the following as a young cleric:

Necessarily demands brotherhood from people, without which the communal possession of goods seems impossible. This brotherhood is nothing else but the Christian idea of social love. Thus, in this way, the ideal of social love as the zenith of Christian ethical teaching converges with the communist ideal at its peak, when it comes to the realization of this ideal in the area of possessing material goods by people. Because of that when choosing between ideals, the Church must choose the communist ideal over the principle of private property.

And later, as pope:

Catholic social doctrine is not a surrogate for capitalism. In fact, although decisively condemning “socialism,” the church, since Leo XIII’s Rerum Novarum, has always distanced itself from capitalistic ideology, holding it responsible for grave social injustices. In Quadragesimo Anno Pius XI, for his part, used clear and strong words to stigmatize the international imperialism of money.

The latter quote, by the way, was spoken in Soviet-occupied Latvia in 1993. Even when criticizing the Soviet empire, John Paul II was careful to distance himself from capitalist orthodoxy.

I am old enough that I was alive and becoming increasingly politically aware when that was happening, and remember how incensed talking heads in the US media generally were when the Pope had the temerity to criticize capitalism. It was one of the things that made me realize the mass media were not nearly so free and impartial as I was told they were. But I digress.

It is not just the brutality of left-wing authoritarianism that John Paul II tangled with, either. He, and local bishops and cardinals, also played key roles in undermining both the Pinochet and Marcos dictatorships. Cardinal Jaime Lachica Sin is in fact widely regarded as one of the leaders of the revolution that toppled the Marcos dictatorship.

Of particular importance is that all these regimes fell, and in relatively short order (it didn’t take multiple decades).

My point here is not to gloss over or deny the conservative aspects of Catholic teaching. Those exist and are very real. My point is that Catholic teaching is more than just that. It aligns neatly with neither the political Right nor the political Left in the modern context. It is the result of a two-millennia old faith tradition, and an organization that sees itself as the custodian of that tradition, and not a creature of current sentiments.

I would also have to say that the Catholic Church’s less than stellar record in dealing with 20th century fascism (and remorse over the same) probably has something to do with it. It started with the Holy See signing the Lateran Treaty with the Mussolini regime. That particular treaty resolved a lot of ambiguity about the role of the pope in modern Europe (it created the Vatican City as an independent microstate), and is widely regarded as one of Mussolini’s few good accomplishments. Because of how well collaborating with the fascist regime in Italy turned out, the Vatican then chose to cut a deal with the fascist regime in Germany. The icing on the cake was Vatican’s complicity in setting up the ratlines that helped many Nazi war criminals escape justice.

It is thus reasonable to suspect that guilt for past misdeeds is part of the current willingness to criticize authoritarianism. Ultimately, though, that is a moot point. However that willingness emerged, it is there, it is deep-seated, and it has a past track record of success.

In this light, I suggest that the current spat between the Trump Regime and the Catholic Church is probably a good sign that the days of the former are in all likelihood limited.

Bypassing Cloudflare to Scrape a Web Site

Published at 21:49 on 15 April 2026

It’s supposed to be really hard, and Cloudflare does indeed to a very good of detecting (and banning) web scrapers. But, it turns out that this is one of those things that, while indeed very difficult to do in the general case, is actually quite simple in a lot of specific cases.

The main trick is to use Playwright (with the playwright_stealth addon) to control a browser, and to use that browser to scrape the web. You could theoretically use some other browser automating tool like Selenium to do this, but the problem with Selenium is that it basically advertises itself with every request (and there is no way to turn this off), and that triggers Cloudflare in short order.

The second trick is to mimic a human user as faithfully as possible. Generally, that means going slow, i.e. no faster than a human would navigate a web page, and inserting randomness into the process so it looks like a human and not an automaton is controlling the browser. This is where things break down for abusive scrapers like AI companies; they can’t take it slow, because if they do, it will literally take millennia to get as much data as they want. But I am not an AI company, and only need to scrape a modest amount of data, so taking it slow is good enough (I just let it run, and the results get collected eventually, not as fast as they might otherwise have been, but it still beats manual cutting and pasting).

The reason I mention this is that, if you try searching on how to do this, the results tend to be pretty useless. They are dominated by either a) techniques that no longer work and which will trigger Cloudflare almost instantly, or b) commercial scraping services interested in taking your money. The latter may actually be a useful service if you want to scrape a lot, but I am not in that category.

That all of this is even necessary to write about is yet another data point in the overall enshittification of the Internet, which by my reckoning peaked in its usefulness circa 2010 and has been heading downhill ever since. The services I now have to use devious techniques to scrape used to be easily scrapable; actually, in many cases, they had free API’s designed to work well with another computer and didn’t need to be scraped at all.

And yes, the abusive scrapers are as much (or more) to blame here as are the sites removing functionality. I have had to implement anti-scraping measures on a site I host, because AI companies were ignoring robots.txt and scraping the daylights out of it. It was so bad that I was getting server crashes from the abuse.

Downtown Vancouver Compass Directions: A Proposal

Published at 08:51 on 11 April 2026

If you live in Vancouver, you know why this is needed without any explanation: the streets in Downtown are canted at approximately a 45˚ angle from the cardinal compass points, as a result of the desire to better align them with the shoreline of Vancouver Harbour.

This of course makes giving directions awkward: “Head north on Granville Street.” But Granville Street doesn’t run either north or south. What does that mean? This proposal offers a concise solutions.

Define “north” to mean “towards Vancouver Harbour” and “west” to mean “towards Stanley Park” and it all sorts out. Plus, this makes sense. Vancouver Harbour is in the same direction as the North Shore, which has “north” as part of its name. Correspondingly, the neighbourhood that borders Stanley Park is known as the West End.

Pedants upset by the fact that these terms do not align with their traditional meaning can be placated by referring to them as “grid north,” “grid west,” etc.

This is something I have always done in my own mind, in fact. But I keep running into pedants who bring up that 45˚ cant. Now I have some rhetorical ammunition at the ready.

Another Javascript Problem: Libraries

Published at 08:26 on 5 April 2026

One of the nice things about C# and Python is that both come with a robust, comprehensive standard library. Java, too: although its standard library tends to be awkward and clunky to use, it is still comprehensive and well documented.

Javascript? Not so much. As part of its heritage of originally being a relatively small, client-side language for embedded scripting, its built-in library is not nearly so comprehensive. One must instead go to npm for many things that are supported out of the box in many other programming languages. Thankfully, as a result of Javascript’s popularity, npm is very comprehensive.

Unfortunately, the quality of the libraries published there (and the quality of their documentation) is, let me just say, erratic. Plus, there’s just so many of them, and it is not always obvious which libraries are better-supported and higher-quality, often resulting a fair amount of trial and error before one finds a suitable solution. Then there is the module and import hell I have written of before; sometimes a given module is not available in the module and import configuration you are currently using, causing you to have to deal with all sorts of uniquely Javascript headaches that no decent programming language has.

In short, if you write an application in Javascript, you’re not going to be able to find reasonable, well-documented default library solutions as often as you would were you using a better-designed, better-planned programming language. Finding and using the right libraries is going to be a source of recurring headaches.

How This Probably Ends

Published at 22:11 on 31 March 2026

I will start with a disclaimer: Trump can be famously unpredictable, and in this situation he is particularly so. So it may well end differently. But, I still think the most likely resolution is that Trump gives up without effecting regime change in Iran. He will of course in all likelihood declare victory, but the Islamic Republic will still exist and may even be allowed to persist in collecting tolls from vessels passing through the Strait of Hormuz.

Even in the former case, this will constitute a win for Iran, because all Iran had to do to win was to survive the onslaught from a vastly more powerful aggressor (actually, from two aggressors, one of them a superpower). Such is the nature of asymmetric conflict.

It will particularly be a win for Iran if they get away with extracting tolls indefinitely, as the war started without Iran having this power. Sure, Iran will have paid a terrible price in lost lives and destroyed infrastructure, but it will in this case emerge with more, not less, power and influence as a result of the war. By any reasonable definition, “emerge with more power and influence” defines the party considered the victor.

Correspondingly, the USA will in all likelihood emerge with less power and influence, as a result of alienating both its allies and the world community by launching an ill-planned and economically disruptive conflict. Trump may well elect to put a cherry on top of the sundae by withdrawing the USA from NATO (an action that technically must require Senate ratification, but the USA is so far gone from the principles of constitutional rule that this doesn’t much matter anymore). If so, this will particularly make it a loss for the USA.

Even if it ends via more protracted process, it still probably ends in a loss for the USA. Again, such is the nature of asymmetric warfare. This is a big part of the reason why no other president save Carter (who launched a very limited operation aimed at liberating the hostages in the US Embassy in Tehran) has opted to attack Iran: the basic asymmetry of any hypothetical conflict has always been strongly in Iran’s favour.