<?xml version="1.0" encoding="utf-8"?>



<feed xmlns="http://www.w3.org/2005/Atom"
    xmlns:fh="http://purl.org/syndication/history/1.0"
    xmlns:at="http://purl.org/atompub/tombstones/1.0">

    <title>Publ: Development Blog</title>
    <subtitle>A personal publishing system for the modern web</subtitle>
    <link href="http://publ.beesbuzz.biz/blog/feed?tag=pushl" rel="self" />
    <link href="http://publ.beesbuzz.biz/blog/feed" rel="current" />
    <link href="https://busybee.superfeedr.com" rel="hub" />
    
    <link href="http://publ.beesbuzz.biz/blog/feed?date=2019-04" rel="prev-archive" />
    
    
    <link href="http://publ.beesbuzz.biz/blog/" />
    <fh:archive />
    <id>tag:publ.beesbuzz.biz,2020-01-07:blog</id>
    <updated>2025-01-05T19:25:49-08:00</updated>

    
    <entry>
        <title>Publ + Pushl releases and a bunch of plans</title>
        <link href="http://publ.beesbuzz.biz/blog/930-Publ-Pushl-releases-and-a-bunch-of-plans" rel="alternate" type="text/html" />
        <published>2025-01-05T19:25:49-08:00</published>
        <updated>2025-01-05T19:25:49-08:00</updated>
        <id>urn:uuid:448a6793-87ae-5753-bf62-2ac50f10867e</id>
        <author><name>fluffy</name></author>
        <content type="html">
<![CDATA[
<p>There&rsquo;s been a few releases of both Publ (now on 0.7.35) and Pushl (now on 0.4.0). A pretty decent amount has changed!</p><p>Publ changes since 0.7.31:</p>
<ul>
<li>Fix some error handling issues causing an ISE</li>
<li>Add support for HTTP <code>Accept:</code>, properly allowing multiple templates with the same name and providing <a href="http://publ.beesbuzz.biz/manual/324-Templating-Guide#template-mapping">reasonable fallback behavior</a></li>
<li>Improve the <code>Content-Type</code> handling in general</li>
<li>Fix some markup-safe handling bugs</li>
</ul>
<p>Note that in order to upgrade to 0.7.35 you&rsquo;ll also need to restrict your Python environment to use a Python version &lt; 3.13; more on that in a bit.</p><p>Pushl changes since v0.3.5:</p>
<ul>
<li>Tidy up some code rot</li>
<li>Actually send an <code>Accept:</code> header</li>
<li>Removed lxml + Pingback support, which has never actually been useful</li>
</ul>
<p>So, let&rsquo;s talk about these projects and some other related stuff.</p>

<h3 id="930_h3_1_Tech-debt"><a href="http://publ.beesbuzz.biz/blog/930-Publ-Pushl-releases-and-a-bunch-of-plans#930_h3_1_Tech-debt"></a>Tech debt</h3><p>Publ has quite a lot of tech debt.</p><p>Most of the testing is done in an ad-hoc smoke-testing manner, and this has sometimes made it difficult for me to work on new features. (Of course I also am the only person working on these features, so I only prioritize things that I personally need.)</p><h4 id="930_h4_2_Pony"><a href="http://publ.beesbuzz.biz/blog/930-Publ-Pushl-releases-and-a-bunch-of-plans#930_h4_2_Pony"></a>Pony</h4><p>One particular issue is that it relies heavily on <a href="https://ponyorm.com">Pony</a>. Pony is a great ORM for doing quick application prototyping stuff, but unfortunately it&rsquo;s been a problem for quite some time:</p>
<ul>
<li>It makes proper unit testing significantly more difficult (it&rsquo;s actually the main reason the testing is in such a sorry state right now)</li>
<li>New Python versions usually end up breaking its clever code generator (which is why Publ 0.7.35 requires you to restrict your Python version)</li>
<li>It never gained support for schema migrations (which, thankfully, Publ was designed to not need to begin with, but this hampers some of my other plans)</li>
<li>General community support just never really materialized</li>
</ul>
<p>To address many of these problems, I&rsquo;ve been wanting to move to another database abstraction; I will most likely use <a href="https://www.sqlalchemy.org/">SQLAlchemy</a>. Whether I use its ORM or not is something I&rsquo;m still trying to decide.</p><h4 id="930_h4_3_Whoosh"><a href="http://publ.beesbuzz.biz/blog/930-Publ-Pushl-releases-and-a-bunch-of-plans#930_h4_3_Whoosh"></a>Whoosh</h4><p>Similarly, full-text search uses <a href="https://pypi.org/project/Whoosh/">whoosh</a>, which has been more or less abandoned. I have updated to use <a href="https://pypi.org/project/Whoosh-Reloaded/">whoosh-reloaded</a>, a community fork that has fixed most of the more egregious issues, but there are still a lot of issues with it:</p>
<ul>
<li>Its locking behavior is difficult to work with (and can cause a lot of operational difficulty)</li>
<li>Its ingest is slow and not easily threadable</li>
<li>Updating the index can be difficult and fragile</li>
<li>It stores the index on the local filesystem which can be a problem for many deployment scenarios</li>
<li>It puts <em>way</em> too much structured into its structured queries, and is overkill for the kinds of query representation Publ needs</li>
</ul>
<p>Unfortunately there aren&rsquo;t as many existing full-text search implementations for Python. My expectation for now is that I&rsquo;ll roll my own using the algorithms described in <a href="https://bart.degoe.de/building-a-full-text-search-engine-150-lines-of-code/">Bart de Goede&rsquo;s article</a>, although this doesn&rsquo;t feel like a great way to do things either.</p><h4 id="930_h4_4_Misaka"><a href="http://publ.beesbuzz.biz/blog/930-Publ-Pushl-releases-and-a-bunch-of-plans#930_h4_4_Misaka"></a>Misaka</h4><p>Finally, the Markdown engine currently used by Publ has been abandoned and is unlikely to continue to working in the long term. It&rsquo;s always been a bit of an operational problem, as well, because it relies on Hoedown (which has been abandoned for ages and never even got updated with HTML 5 support) and requires being able to either retrieve architecture-specific binaries or being able to build them yourself. The build process has been <em>mostly</em> easy for most users, but it&rsquo;s still not ideal.</p><p>Fortunately, I&rsquo;ve been playing with other Markdown implementations on other projects, and I&rsquo;m fairly certain that I&rsquo;ll be happy with <a href="https://github.com/lepture/mistune">Mistune</a> instead. Switching to that will require reimplementing a bunch of stuff in Publ, but it&rsquo;s all stuff I&rsquo;d been wanting to fix anyway.</p><p>In particular, I&rsquo;ve been wanting to figure out a way to templatize footnotes (for example, letting people make use of <a href="https://edwardtufte.github.io/tufte-css/">Tufte sidenotes</a> or putting a <code>&lt;details&gt;</code> reveal inline or after the current paragraph or the like), and there&rsquo;s a lot that could be better about how image sets are currently handled, and ideally I&rsquo;d be able to templatize those as well.</p><h3 id="930_h3_5_Comments"><a href="http://publ.beesbuzz.biz/blog/930-Publ-Pushl-releases-and-a-bunch-of-plans#930_h3_5_Comments"></a>Comments</h3><p>The main ways that I&rsquo;ve handled comments on Publ-based sites is either:</p>
<ul>
<li><a href="https://webmention.io/">webmention.io</a> + <a href="https://github.com/PlaidWeb/webmention.js">webmention.js</a></li>
<li><a href="https://isso-comments.de">isso</a></li>
</ul>
<p>Both of these are Fine™ for simple usage but they run into a bunch of issues on larger sites, and also the UX just isn&rsquo;t really where I&rsquo;d like it to be.</p><p>I wrote a <a href="https://beesbuzz.biz/blog/7457-Some-thoughts-on-comments">much more detailed blog post</a> on my main site, but the short version is that I&rsquo;d like to make a comment system that works more closely with Publ (or any other publishing framework) that stores things locally and supports both local posts <em>and</em> webmention (both sending and receiving), and which would also accept user data from the publishing stack.</p><p>I&rsquo;m thinking it would take the form of a Python library that you can embed into an app (with easy hooks for Flask), but would also offer its own Flask frontend for hosting it as an embeddable app instance that can be used from non-Python things.</p><h3 id="930_h3_6_ActivityPub"><a href="http://publ.beesbuzz.biz/blog/930-Publ-Pushl-releases-and-a-bunch-of-plans#930_h3_6_ActivityPub"></a>ActivityPub</h3><p>Native ActivityPub support has been at the back of my mind for a while. Having its own built-in webmention endpoint would also make for a nice spot to start adding in ActivityPub, since ActivityPub verbs aren&rsquo;t fundamentally different from Webmention verbs.</p><p>The main thing this would bring to the table is being able to set up various outboxes for different views (for example, <code>@blog@example.com</code> for just blog posts or <code>@all@example.com</code> for everything), and then also being able to make use of the user permissions to send private entries as DMs to the authorized subscribers, reducing the need for private entry stubs (which are bad UX all around and which I only adopted as a compromise because <a href="http://publ.beesbuzz.biz/blog/1266-Why-Publ-won-t-support-magic-auth-links">magic links have problems</a> and feed readers <em>still</em> don&rsquo;t support bearer tokens or <a href="https://indieweb.org/Ticketing_for_IndieAuth">Ticket Auth</a>).</p><h3 id="930_h3_7_Documentation"><a href="http://publ.beesbuzz.biz/blog/930-Publ-Pushl-releases-and-a-bunch-of-plans#930_h3_7_Documentation"></a>Documentation</h3><p>Also, having had to actually consult the docs while building a new Publ-based website, I&rsquo;ve come to realize just how bad a disaster the <a href="http://publ.beesbuzz.biz/manual/">manual</a> currently is. It could really do with some reorganization at the very least.</p><h3 id="930_h3_8_In-conclusion"><a href="http://publ.beesbuzz.biz/blog/930-Publ-Pushl-releases-and-a-bunch-of-plans#930_h3_8_In-conclusion"></a>In conclusion</h3><p>I have a lot of stuff I want to work on and hopefully I get somewhere with some of these things this year. If you&rsquo;d like to help out, you can make code contributions, or you can make financial contributions via <a href="https://ko-fi.com/fluffycritter">Ko-Fi</a>, <a href="https://patreon.com/fluffy">Patreon</a>, or <a href="https://github.com/sponsors/fluffy-critter">GitHub Sponsors</a>. But no pressure.</p>

]]>
        </content>
    </entry>
    
    <entry>
        <title>Pushl v0.3.5</title>
        <link href="http://publ.beesbuzz.biz/blog/2-Pushl-v0.3.5" rel="alternate" type="text/html" />
        <published>2023-01-04T20:17:35-08:00</published>
        <updated>2023-01-04T20:17:35-08:00</updated>
        <id>urn:uuid:ec83f798-f65b-5c00-bbd7-90e61660aa55</id>
        <author><name>fluffy</name></author>
        <content type="html">
<![CDATA[
<p>Pushl has been updated to be compatible with an API change made in Python 3.11, specifically fixing some functionality which was deprecated in Python 3.8 and which I somehow failed to notice the deprecation warning of.</p><p>Thanks to @seirdy for <a href="https://github.com/PlaidWeb/Pushl/issues/49">bringing this to my attention</a>.</p>

]]>
        </content>
    </entry>
    
    <entry>
        <title>Pushl v0.3.3</title>
        <link href="http://publ.beesbuzz.biz/blog/94-Pushl-v0.3.3" rel="alternate" type="text/html" />
        <published>2021-09-01T21:08:27-07:00</published>
        <updated>2021-09-01T21:08:27-07:00</updated>
        <id>urn:uuid:80557272-d7e1-5c47-bbd8-ad25c35d7e7d</id>
        <author><name>fluffy</name></author>
        <content type="html">
<![CDATA[
<p><a href="https://pypi.org/project/Pushl">Pushl</a> has been updated, specifically to rewrite the way that feeds are parsed to avoid a problem due to feedparser internals changing in a way that made the caching mechanism stop working.</p>

]]>
        </content>
    </entry>
    
    <entry>
        <title>Pushl v0.3.0, and some terminology changes</title>
        <link href="http://publ.beesbuzz.biz/blog/745-Pushl-v0.3.0-and-some-terminology-changes" rel="alternate" type="text/html" />
        <published>2020-06-20T02:11:59-07:00</published>
        <updated>2020-06-20T02:11:59-07:00</updated>
        <id>urn:uuid:166f24d7-4861-5ff7-b6d5-a467a96454ab</id>
        <author><name>fluffy</name></author>
        <content type="html">
<![CDATA[
<p>Pushl v0.3.0 is now out. Changes since v0.2.14:</p>
<ul>
<li>Some caching fixes</li>
<li>Updates to some antiquated terminology</li>
</ul>
<p>Per the above, the main code branch<sup id="r_e745_fn1"><a href="http://publ.beesbuzz.biz/blog/745-Pushl-v0.3.0-and-some-terminology-changes#d_e745_fn1" rel="footnote">1</a></sup> is now called <code>main</code>, and you include and exclude link <code>rel</code> attributes with <code>--rel-include</code> and <code>--rel-exclude</code>, in keeping with some long-overdue naming convention updates.</p><p>We&rsquo;re all in this together.</p>

]]>
        </content>
    </entry>
    
    <entry>
        <title>Pushl v0.2.14, Authl v0.3.4</title>
        <link href="http://publ.beesbuzz.biz/blog/395-Pushl-v0.2.14-Authl-v0.3.4" rel="alternate" type="text/html" />
        <published>2019-12-03T23:28:32-08:00</published>
        <updated>2019-12-03T23:28:32-08:00</updated>
        <id>urn:uuid:4ca8abe2-5474-531c-b9a5-17d280d3bf85</id>
        <author><name>fluffy</name></author>
        <content type="html">
<![CDATA[
<p>Double-whammy release today.</p>

<h3 id="395_h3_1_Pushl-changes"><a href="http://publ.beesbuzz.biz/blog/395-Pushl-v0.2.14-Authl-v0.3.4#395_h3_1_Pushl-changes"></a>Pushl changes</h3>
<ul>
<li>Released the <a href="http://publ.beesbuzz.biz/blog/20191201 pushl 0.2.13.md">previously-mentioned redirection fix</a></li>
<li>Added support for mf2 (<code>h-feed</code>/<code>h-entry</code>) feeds</li>
</ul>
<p>Now all you &ldquo;RSS is dead&rdquo; folks have no excuse not to use Pushl. 😘</p><h3 id="395_h3_2_Authl-changes"><a href="http://publ.beesbuzz.biz/blog/395-Pushl-v0.2.14-Authl-v0.3.4#395_h3_2_Authl-changes"></a>Authl changes</h3>
<ul>
<li>Backend improvements:

<ul>
<li>Renamed the Mastodon handler to Fediverse (since it turns out it supports Pleroma too!)</li>
<li>Enabled static analysis in the build process</li>
</ul></li>
<li>Flask frontend improvements:

<ul>
<li>Improved the login flow for people who are running without Javascript</li>
<li>Modernized the JavaScript in the login method probe, and made minor UX
improvements there too (sorry to anyone who&rsquo;s still stuck on an
<a href="https://caniuse.com/#feat=async-functions">ancient browser</a>, but at
least login should still work!)</li>
<li>Improved error handling in the login flow; the singular error is passed
along to the template (instead of using Flask message flashing),
and the login form will be pre-filled with the last URL attempted.</li>
</ul></li>
</ul>


]]>
        </content>
    </entry>
    
    <entry>
        <title>Pushl v0.2.13</title>
        <link href="http://publ.beesbuzz.biz/blog/711-Pushl-v0.2.13" rel="alternate" type="text/html" />
        <published>2019-12-01T21:10:13-08:00</published>
        <updated>2019-12-01T21:10:13-08:00</updated>
        <id>urn:uuid:29ecf448-bbfd-5902-9524-900171e78bcf</id>
        <author><name>fluffy</name></author>
        <content type="html">
<![CDATA[
<p>I&rsquo;ve released a new version of <a href="https://github.com/PlaidWeb/Pushl">Pushl</a>.</p><p>Changes since the last version:</p>
<ul>
<li>Added support for tracking entry URL changes</li>
<li>Finally got around to adding type annotations and static analysis</li>
</ul>


<p>There are three ways in which an entry URL may change:</p>
<ol>
<li><p>The entry item&rsquo;s link in the feed changed, and the old link now redirects</p><p>Previously, Pushl would try retrieving the old URL, would get redirected to the new URL, and then would only send updates for any target URLs which changed, coming from the new URL. It would also see the new URL as a separate entry and send out pings from it. At best, this meant that there would be duplicated pings from the old and new URLs.</p><p>Now, it sees that the source URL has changed and re-sends all of the old pings from the old URL, which lets the endpoint know that the URL has changed and should be updated. (It also sends a fresh set of pings from the new URL, which will at least theoretically be ignored by the endpoint, if it&rsquo;s implemented correctly.)</p></li>
<li><p>The entry item&rsquo;s link in the feed changed, and the old link now generates an error</p><p>This path hasn&rsquo;t changed at all; Pushl saw the old URL as a deletion, and the new one as an addition, and either way would send out pings for all targets from both URLs.</p></li>
<li><p>The feed linked to it via a redirection URL (such as a short link or a tracking link), and the redirection changed</p><p>Previously, Pushl would not see this as as change at all in the entry, and would not send out any updates at all for old targets. This causes all sorts of potential failures not worth enumerating.</p><p>Now, it sees that the destination changed, and re-sends all pings from the old target URL, telling the endpoint to update them.</p><p><em>However,</em> this has now introduced a bug which I didn&rsquo;t realize until writing up this explanation: it only works if the old redirected URL also redirects to the new entry URL, in which case it behaves like case 1 above. If the old URL now errors, this will appear as a deletion to the endpoint, and all of the mentions go away &ndash; and Pushl won&rsquo;t ever try to re-send them.</p><p><del>So, I&rsquo;ve already made a <a href="https://github.com/PlaidWeb/Pushl/commit/17fd5ac24f4cb50384d3d8289619ea932b680ff2">bugfix</a> (which will go out in the next Pushl release, whenever that is) where the pings are always sent from the original URL in the feed. This way, it&rsquo;s up to the endpoint to see that the redirection updated. This puts the onus on the endpoint to be able to track changes in redirections in the source URL, or always use the source URL verbatim even if it&rsquo;s a redirection. Either way, Pushl is trying its hardest to do the right thing in a tricky situation.</del></p><p><mark>Update:</mark> I rolled back that bugfix, because it had the much worse effect of breaking <code>rel=&quot;canonical&quot;</code>. A better solution would be to <a href="https://github.com/PlaidWeb/Pushl/issues/37">re-send the old pings from the old URL</a> instead. Which is now implemented and tested working.</p></li>
</ol>
<p>In an ideal world, case 3 simply wouldn&rsquo;t happen, but unfortunately, a lot of feeds do this for various reasons. Feedburner is particularly egregious about it, but a lot of blogging platforms do it naturally; Tumblr, for example. And, heck, it&rsquo;s easy to configure Publ to do that too (and it always does this for unauthorized posts, as part of the privacy model).</p><p>Anyway. Consider this fix my day 1 effort for the <a href="https://beesbuzz.biz/blog/3640-My-IndieWeb-Challenge-2019-aspirations">IndieWeb 2019 Challenge</a>.</p>

]]>
        </content>
    </entry>
    
    <entry>
        <title>Pushl v0.2.12</title>
        <link href="http://publ.beesbuzz.biz/blog/796-Pushl-v0.2.12" rel="alternate" type="text/html" />
        <published>2019-10-03T01:49:17-07:00</published>
        <updated>2019-10-03T01:49:17-07:00</updated>
        <id>urn:uuid:14daec75-e041-59ba-b09f-2e91ca5c1538</id>
        <author><name>fluffy</name></author>
        <content type="html">
<![CDATA[
<p>I have now released Pushl v0.2.12. The following is new:</p>
<ul>
<li>It now respects <code>rel=&quot;canonical&quot;</code> or <code>rel=&quot;self&quot;</code> when determining which URL to send a WebSub ping for</li>
<li>You can now send self-pings using the <code>--self-pings</code> parameter</li>
<li>Miscellaneous code cleanups</li>
</ul>


]]>
        </content>
    </entry>
    
    <entry>
        <title>Pushl v0.2.11</title>
        <link href="http://publ.beesbuzz.biz/blog/337-Pushl-v0.2.11" rel="alternate" type="text/html" />
        <published>2019-09-23T09:33:49-07:00</published>
        <updated>2019-09-23T09:33:49-07:00</updated>
        <id>urn:uuid:a48e9bee-4de3-5dd5-897a-e5c115bd58bf</id>
        <author><name>fluffy</name></author>
        <content type="html">
<![CDATA[
<p>In trying to fix what looked like a bug in Pushl (which turned out to be a bug in one of the services I was pinging), I did a bunch of much-needed code cleanup and refactoring.</p><p>I also added the ability to ping the Internet Archive Wayback Machine for outgoing links if the target has changed (relative to the usual <code>If-Modified-Since</code>/<code>If-None-Match</code> tests).</p><p>Pushl will now also log warnings for two useful situations:</p>
<ul>
<li>An outgoing link generates a 400-class error (403/404/410/etc.)</li>
<li>An outgoing webmention has a different canonical URL than what&rsquo;s being pinged (improved since <a href="http://publ.beesbuzz.biz/blog/965-Pushl-v0.2.8">v0.2.8</a>)</li>
</ul>
<p>The way it handles canonical URLs is also now improved; if a page has <code>&lt;link rel=&quot;canonical&quot;&gt;</code> it will use that, otherwise it will use the final URL that is the result of chasing redirects.</p>

]]>
        </content>
    </entry>
    
    <entry>
        <title>Pushl v0.2.8</title>
        <link href="http://publ.beesbuzz.biz/blog/965-Pushl-v0.2.8" rel="alternate" type="text/html" />
        <published>2019-08-21T22:21:22-07:00</published>
        <updated>2019-08-21T22:21:22-07:00</updated>
        <id>urn:uuid:60069224-4aef-5de0-bec8-f1d8eda628cf</id>
        <author><name>fluffy</name></author>
        <content type="html">
<![CDATA[
<p>I&rsquo;ve released v0.2.8 of Pushl, which fixes an issue with Webmention and Pingback where it was over-optimistically setting the link target. It will also warn you if the link target doesn&rsquo;t match with the actual page, so you can update your links accordingly.</p><p>Right now it&rsquo;s a <em>little</em> spammy (in that it&rsquo;ll tell you about redirection mismatches for all links, not just ones with a Webmention or Pingback endpoint), but the next version will address that.</p>

]]>
        </content>
    </entry>
    
    <entry>
        <title>Pushl v0.2.7</title>
        <link href="http://publ.beesbuzz.biz/blog/1303-Pushl-v0.2.7" rel="alternate" type="text/html" />
        <published>2019-08-12T17:25:28-07:00</published>
        <updated>2019-08-12T17:25:28-07:00</updated>
        <id>urn:uuid:6a03b460-190c-5ae0-8d5c-800722e4bc68</id>
        <author><name>fluffy</name></author>
        <content type="html">
<![CDATA[
<p>Around a month ago a bunch of my webmention stuff broke on my site, and I just figured out what was causing it. Pushl was getting confused by the fact that I had multiple feeds which provided the same content, and some of them were in a no-webmentions context. The no-webmentions ones were getting processed first, which was preventing the webmention-context versions from actually being processed.</p><p>So, I fixed this bug by making the context part of what dedupes the actions.</p><p>Every time I work on Pushl I feel like it could use a major rewrite, incidentally. This is one of those times.</p>

]]>
        </content>
    </entry>
    

    
</feed>