Ephes Blog

Miscellaneous things. Mostly Weeknotes and links I stumbled upon.


Weeknotes 2023-05-01

, Jochen
I'm a normal person, in the mathematical sense. --Johannes Spielmann
Midjourney generated tulips


Last week, I worked on updating django-cast to support Wagtail 5 (which is set to release tomorrow) and Django 4.2:

  • Released version 0.3.0 of wagtail_srcset, which includes a workaround for the image_node.filter_spec -> image_node.filter_specs renaming in Wagtail 5, along with some tox fixes and test image cleanup after testing.
  • Released version 0.2.14 of django-cast , adding support for Wagtail 5 and Django 4.2.
  • Ran python-podcast.de and wersdoerfer.de on the Wagtail 5 release candidate and Django 4.2 for a week to identify any potential issues (none found).

Another topic I focused on last week was Vue.js. I attended the revived Vue.js Cologne meetup, which was enjoyable, and began developing a Vue theme for django-cast. I even managed to record a live-stream about it. Integrating Vue.js into Django proved easier than anticipated, perhaps due to assistance from my LLM robot friends. While I'm not a huge fan of single-page applications (SPAs) and frontend frameworks in general, I want to keep my options open and be able to justify my preferences.

In terms of meetups, I attended a Java User Group Düsseldorf event to see the talk "Die Welt vor 10 Jahren mit Stefan Tilkov / Eberhard Wolff - live von der RheinJUG". I found it quite interesting. However, despite attending numerous local meetups, I didn't recognize any of the attendees. It's fascinating how disjunct various IT-related communities can be.

Melia Hotel RheinJUG

In "Slavoj Žižek: „Paradoxien der Mehrlust“ - Ein gegenwartskritischer Rundumschlag" (starting at 06:00), an amusing moment arises as Žižek discusses LLM creativity. He claims that human creativity stems from our ability to harness contingency in random mistakes, referencing Heinrich von Kleist. Ironically, his poetic description of what LLMs can't do is spot-on for how they function technically. The 'temperature' parameter even allows for adjustable creativity by controlling how much contingency is added. Although I have often expressed my disdain for uninformed discussions about topics I am knowledgeable in, this instance has proven that they can be surprisingly entertaining, and I stand corrected.

Articles

Software

Mastodon / Twitter

Weeknotes

Video

Papers

Podcast

Out of Context Images


Weeknotes 2023-04-24

, Jochen
Me, walking up to the front desk of the hotel: I have a weird question
Clerk: there are no weird questions
Me: I have an NFC chip implanted in my hand, and I was wondering whether you'd be willing to enroll it as a new key for my room
Clerk: you want me to do what?? I need to see this. What room?
Didn't even ask for ID.--Quinn Wilton
Btconf via midjourney


This past week was quite eventful 😅. On Monday morning, I had an emergency dental appointment due to a broken tooth crown 😬. Following that, I attended the Beyond Tellerrand conference on Monday and Tuesday, which proved to be an excellent experience filled with inspiring talks and engaging conversations with fellow attendees. A special shoutout and warm greetings to the hosts of the WWSIV podcast 🎙️!

Throughout the week, I attempted to make django-cast compatible with the upcoming Wagtail 5 release, but faced challenges mainly due to the usage of modules from 'wagtail.core' in migrations 🐛 and the removal of 'image_node.filter_spec' attribute. Additionally, I had to resolve an issue with old comments being invisible on python-podcast.de as a result of the migration to Wagtail and changes to the Django episode model's primary keys 🔧 - thanks to Norbert for the heads up. Unfortunately, there was no django-cast release this week 😞.

In my spare time, I delved into my new LLM hobby by starting to read the "Natural Language Processing with Transformers" book 📚. On Friday morning, I attended a Creative Mornings talk discussing ChatGPT and midjourney, though it didn't present much new information for me 🤷‍♀️ but the room was packed and there seems to be a lot of buzz around this topic. Later that day, I attempted to record a screencast with Manuel about the "nlp with transformers"-book and some LLM implementation stuff, but we faced technical difficulties with real-time collaboration on Jupyter notebooks. I subsequently wrote a TIL post about the experience, hoping that for our next screencast, it will work better 🤞.

Lastly, I managed to take some time and enjoy the outdoors – very good! 🌳

Articles

Weeknotes / Newsletter

Software

Cool Websites

Podcasts

Out of Context Images


TIL: Real-time Collaboration for Jupyter Notebooks

, Jochen

While preparing a screencast with Manuel, we searched for real-time collaboration tools for Jupyter notebooks. JetBrains' "Code With Me" proved unsuitable, displaying only raw JSON. Here are two practical alternatives:

  1. Visual Studio Code's "Live Share" extension
  2. Launching JupyterLab server like this: jupyter-lab --collaborative

If you're aware of other collaboration tools for Jupyter notebooks suited for screencasts, please drop me a note 😄!


Weeknotes 2023-04-17

, Jochen
I use keming as an adjective to describe bad kerning --Xe

Worked a little bit on the upcoming pytest-course. My wife made a website for Thomy Saurk which was going live last week. Then there was a new django-cast release. It provides some fixes for the podcast_audio field (if it's not set there's no twitter-card and the episode is not showing up in the feed) and it's now possible to add custom templates for error views (for 404, 500, 403 etc HTTP status codes) if you create a theme for django-cast.

And after two or three years of using PyCharm or vs code for writing Python almost exclusively, I started to use vim and neovim again and spent already a significant amount of time on their configuration 😅. But I missed using vim for sure.

Articles

Video

Books

Weeknotes

Mastodon / Twitter

Software

Podcasts


TIL: Validating Wagtail Page Fields Only Upon Publishing

, Jochen

Recently, I encountered an issue when publishing a podcast episode about LLMs using django-cast. The episode failed to appear in the podcast feed and the announcement tweet lacked the newly added Twitter card. The cause? I forgot to include the podcast_audio field.

Ideally, the system should have displayed an error when attempting to publish an episode without the podcast_audio field. However, we still want to allow draft episodes to be saved without the audio field.

Initial Solution Suggested by ChatGPT

For this LLM-focused episode, I initially sought guidance from ChatGPT. It provided a seemingly promising solution that appeared effective upon first inspection:

class MyCustomPage(Page):
    field1 = ...
    field2 = ...
    ...

def clean(self):
    super().clean()

    # Check if the page is being published
    if self.status == 'live':
        # Perform custom validation for required fields
        if not self.field1:
            raise ValidationError({'field1': "Field1 is required for publishing."})
        if not self.field2:
            raise ValidationError({'field2': "Field2 is required for publishing."})

Upon closer examination, the correct condition should have been if self.status_string == "live". However, the proposed solution still didn’t function as intended. Instead of displaying a user-friendly error message in the Wagtail admin interface, attempting to publish an episode without the podcast_audio field resulted in an unwieldy traceback, which would have led to an internal server error in production.

Revised Solution

The previous solution didn't work, because Wagtail only displays a nice error message when the ValidationError is raised while it tries to save a draft revision. Therefore we need to raise the ValidationError during the first call of the clean method where the status_string is still "draft". But how do we know the page is about to be published then?

After tinkering with the before_edit_page hook for a while, I finally landed on this solution:

class CustomEpisodeForm(WagtailAdminPageForm):
    """
    Custom form for Episode to validate the podcast_audio field.

    The reason for this is that the podcast_audio field is not required
    for draft episodes, but it is required for published episodes. So
    we have to check which button was clicked in the admin form.
    """

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields["action-publish"] = forms.CharField(required=False, widget=forms.HiddenInput())

    def clean(self) -> dict[str, Any]:
        cleaned_data = super().clean()
        if cleaned_data.get("action-publish") and cleaned_data.get("podcast_audio") is None:
            raise forms.ValidationError({"podcast_audio": _("An episode must have an audio file to be published.")})
        return cleaned_data


class Episode(Post):
    ...
    base_form_class = CustomEpisodeForm

This CustomEpisodeForm class checks whether the “Save draft” or “Publish” button was pressed in the Wagtail admin and stores the information for use in the clean method. This solution successfully validates the podcast_audio field only upon publishing the episode, while still allowing draft episodes to be saved without the audio field.