Posts in category "Python"

Wasat v1.5.0

1 min read; 12 GFI

I'm still working on the client certificate management PR for Rogallo, which, of course, heavily leans on the API of Wasat. In most cases, I've noticed that something I want to do in the PR can already be done, but the work to perform the action would seem like unnecessary detail in a client application; I want to make using Wasat as frictionless as possible.

With this in mind, v1.5.0 adds interfaces for exporting and importing client certificate data.

Wasat v1.4.0

1 min read; 13 GFI

Another bump to Wasat, this being v1.4.0. This release is in support of some work I want to do on Rogallo, where I intend to add proper client certificate management.

While Wasat provided good support for the generation, storage, and use of client certificates, there was no real public API that would allow for the management of those certificates. This version addresses that.

Now there are methods for doing things like:

  • Listing all client certificates
  • Getting a specific certificate's details
  • Creating a certificate
  • Associating and disassociating a certificate with a URI
  • Deleting a certificate

This should give me everything I need to implement a simple client certificate user interface in Rogallo.

BagOfStuff v2.0.0

1 min read; 9 GFI

I've just made a small update to BagOfStuff, my little support library for my personal Python-based FOSS projects. This release makes some more changes to the history classes, adding an add_or_replace method, and also making some improvements to the type hinting by basing the classes on MutableSequence rather than Sequence.

While the history classes were originally intended to feel immutable, it's obvious that they're really not. The idea was that stuff gets added to them, stuff falls off the other end, and stuff might disappear depending on the context and when stuff gets added. The general idea was that direct manipulation was something that wouldn't happen. So I'd started out with them inheriting from Sequence, and so implying they were a read-only interface.

Given this acknowledgement, they now inherit from MutableSequence. This means that some extra (dunder) methods are added, and it also means that some extra exceptions can be raised. For example: setting slices to iterables isn't supported and will raise a NotImplementedError. Some other slice-based operations aren't supported either.

While this is close to a breaking change, it's fine for my use of this code. However, I had to make one big breaking change: I'd written clear so that it returned Self1. The interface expected by MutableSequence is one that returns None. So to strictly comply with that interface, I've changed the return type.

With this being a breaking change, I've bumped the library version to v2.0.0. While it's really a small change, and only one I'd notice, there's no getting away from the fact that the API has changed. That deserves a major version bump.


  1. I tend to prefer that a method that might return None actually return Self; it allows for chaining. I recognise that there are other schools of thought about this in the Python world; I'm not a member of those schools. 

md2gemtext - A library for converting Markdown to Gemtext

1 min read; 10 GFI

Following on from html2gemtext, the inevitable has happened: I couldn't let the Markdown side of things remain unaddressed. While Rogallo v1.8.0 added some extra rendering of Markdown to make it look more "pretty", I felt it really needed to be handled so it had more utility. Being fully navigable, even by keyboard, seems more important than pretty tables.

So md2gemtext now exists as a library on PyPI. I have two plans for this. While I fully intend to shake up the Markdown support in Rogallo -- either replacing the use of the Textual Markdown widget to display it, or at least giving the user a configuration option to decide how Markdown is displayed -- I also want to pay some attention to my (currently rather simple) Gemini-based log and use this library to build a tool that will convert this blog's Markdown content into Gemtext that looks just how I want it.

As with html2gemtext, this is an early version of this library, and I'm sure there will be edge cases I'll have missed and will want to tidy up. But at the moment the results are looking promising.

I'm once again in a place where I'm actually half-seriously thinking that much of what Hike does could be built into Rogallo, if I were to simply add http(s) support there.

BagOfStuff v1.3.0

1 min read; 11 GFI

For a wee while now I've been trying to nail down a weirdness with the navigation history in Rogallo. I never felt it was a difficult issue to deal with, but it was also one of those issues that I could never obviously recreate at will, and it only seemed to happen while I was busy working on something else.

Yesterday evening I finally managed to come up with a way to always recreate it and, having done so, the solution seems pretty straightforward1. In order to implement the tweak I want, I need to be able to truncate the navigation history, and of course do so in a non-destructive way.

So the history classes in BagOfStuff v1.3.0 have grown clone and truncate methods. This will allow me to duplicate a history, truncate it at its current location, then save it, without affecting the working copy.


  1. Why do I feel like I'll regret saying that? 

Port1900 - An async Python client library for the Nex protocol

1 min read; 10 GFI

It's that time again. Time to add another small web protocol to Rogallo. This time it's one I stumbled across a few days ago: the Nex protocol. This one is very simple and straightforward and it seemed like a shame not to support it.

So, as I have with Gemini, Spartan, Gopher and Finger, I've added a dedicated library for dealing with the associated URI, and to provide a client for talking to the server.

The documentation can be found on the dedicated site.

GopherMap v1.0.0

1 min read; 10 GFI

When I first created GopherMap, I made it pretty strict about what it did and didn't consider a valid map. Unsurprisingly, reality did what reality does and, pretty quickly, Rogallo met maps that didn't fit with this strict approach. So I relaxed things, accepting pretty much anything that even vaguely looked like a Gopher map. This solved the problem.

However, earlier today, I ran into a page that was obviously supposed to be plain text, but was being displayed in part like a map. The problem was my attempt at detecting a reply from a Gopher server that looked like it might be an error. This very relaxed approach to "this is likely some Gopher stuff, let's accept it as such" meant that a text file that had a 3 anywhere in the first column was tripping off the "this is likely some Gopher stuff and it looks like there's an error in there" check. The result? Treated like a Gopher map, converted into Gemtext, and displayed in the wrong way.

So... v1.0.0 has been released which adds some code to help out with this. The default parsing still works as before, but there's now a strict mode which will raise exceptions if some sort of significant problem is found. On top of this are a couple of helper class methods which check if some text is likely a valid map, and check if some text is likely a valid map containing an error.

With these in place, I can update Rogallo so that it's still pretty easy-going when it comes to showing Gopher maps, but isn't quite so laid-back when it comes to finding errors coming back from Gopher servers, and so incorrectly rendering the result.

html2gemtext - A simple library for converting HTML to Gemtext

3 min read; 10 GFI

Yesterday evening, while tinkering with Rogallo, I managed to nerd-snipe myself pretty well. I was playing around with the idea of better presentation of some forms of text/* content. While, of course, Rogallo handles text/gemtext just fine, there are lots of other MIME types that it will show too (pretty much all within text/*). Already, if it can work out an appropriate language, the viewer will do syntax highlighting, and this includes Markdown files. However, Rogallo has a full Markdown widget built right in so I was experimenting with using that as the way to show Markdown content.

Nothing that clever really, all pretty obvious.

But then I got to thinking... In OldNews I heavily rely on html-to-markdown. Given I have a Markdown viewer to hand, if the user ends up trying to look at some text/html, why not convert it over to Markdown and render it that way? That's... doable.

There are, however, some problems with this idea:

  • As useful as html-to-markdown has been for OldNews, I've found it quite unreliable at times, with the occasional breaking change. I don't mention this as a negative about the project, but I don't want another one of my projects sitting on top of a moving target like that.
  • Dragging in a reasonably large dependency for what's likely to be a niche requirement doesn't quite feel right.
  • Textual's Markdown viewer has, to this day, one massive design flaw: links can't be navigated with the keyboard1. I'm doing my absolute best to ensure that Rogallo is keyboard-first. Leaning on this widget for viewing Markdown is one thing, but leaning on the widget for other content types starts to erode that aim.

I did consider the idea of having this feature as an install option, so you'd be able to install rogallo and have it work as normal, or install rogallo[html] (or similar) and it would drag in the ability to render some HTML using this pipeline.

Then I realised: why target Markdown at all? I already have the code for rendering Gemtext, and that solves the keyboard navigation of links problem. How hard could it be to write something to convert HTML to Gemtext?

Turns out, at least for the requirements I have right now, not that hard!

html2gemtext is still in its infancy, but it's doing a passable job of turning most of the HTML I throw at it into reasonable Gemtext. I don't doubt for a moment that there are lots of pages out there that won't turn out right -- for varied values of right -- but so far the results are readable and navigable. The plan now is to keep improving as I run into new cases that could be handled better.

While I've not built this into Rogallo just yet, I think I will make use of it. I'm also giving serious thought to using it for my capsule. Over there I'm adding some posts from this blog and html2gemtext could form the basis of a tool to help automate some of that.

Right now I'm using a script I've written that wraps lowdown to do the Markdown to Gemtext conversion, but the result -- as good as it is -- isn't quite what I'd like. I'm thinking I could tailor the results exactly as I want if I go from this blog's HTML via html2gemtext.

Or, of course, given my blog is written in Markdown, I could next tackle my own just-how-I-need-it Markdown to Gemtext converter...

As for how this new library will go into Rogallo... Using it to render HTML that might be found kicking about in Geminispace or Gopherspace makes sense, I think. That should be enough. It's not like I really need to turn it into an http(s) browser too. Right? Right?!?


  1. This mouse-only problem is a recurring theme in Textual. 

Sybaritic - A Spartan protocol library for Python

1 min read; 9 GFI

Now that Rogallo supports multiple protocols, it's tempting to add one or two more. As of the time of writing, alongside Gemini, both Gopher and Finger are supported. While wandering the small web, I stumbled on the Spartan protocol. Given its similarity to Gemini and the fact it uses Gemtext as its main document type, adding it to Rogallo seemed like an obvious thing to do.

In aid of this, I've created Sybaritic. It is, in effect, a sibling library to Wasat, Port70 and Port79. As with the others, it is async-all-the-way and is designed to have a similar API.

With this in place, I can now extend Rogallo to handle spartan:// URIs as first-class citizens.

Gemtext v1.1.0

1 min read; 12 GFI

I've released a small update to Gemtext. At the moment, I'm working on adding Spartan protocol support to Rogallo, and to do this I need to handle a small extension it makes to Gemtext.

While Spartan is quite different from Gemini in the underlying protocol, it uses Gemtext as the default/standard markup language, but with one small difference. To allow uploaded data that is initiated by the markup, rather than by the server, there is a =: line type. In some respects, this is similar to type 7 items in Gopher maps.

Rather than spin up a whole new library just to support this one small difference, and rather than do some special-case nonsense in Rogallo itself, I've added optional (and turned on by default) support for =:. When encountered, this results in a SpartanPrompt object, which simply inherits from a Link.

Any code that doesn't require this feature can turn it off with the with_spartan_support parameter.