Ephes Blog

Miscellaneous things. Mostly Weeknotes and links I stumbled upon.

Date -

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! 🌳


Weeknotes / Newsletter


Cool Websites


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.





Mastodon / Twitter



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):

    # 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.

Weeknotes 2023-04-10

, Jochen
"for legal reasons this is a joke" --julia, serial project starter

Lots of colored eggs. Short work week where I was collecting some material for an upcoming pytest-course and did some research about this whole shiny new LLM field which is completely wild atm. Recorded a podcast episode about LLMs. Released a new django-cast version with some minor improvements. Fixed a 500 error on this site caused by the csrf-middleware raising an error and context-processors weren't run so the custom error template didn't get its base template (this needs more fixing).


Mastodon / Twitter