Ephes Blog

Miscellaneous things. Not sure what to put here, yet.


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.


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

Articles

Mastodon / Twitter

Freelance

Papers

Weeknotes

Software

Podcasts


Weeknotes 2023-04-03

, Jochen
if my editor reads this: everything’s totally fine --Ethan Marcotte

Not much work, but a fair share of paperwork, and finally traveled to Erlangen. New django-cast-release and applied with django-cast to the prototype fund🤞. Downloaded the LLaMA weights, and hope to find some time to play around with LLMs locally next week.

Articles

Weeknotes

Mastodon / Twitter

Open Source Funding

Software

Podcasts