Feeds
PyCharm: Introducing the PyCharm Databricks Integration
We’re introducing the Databricks integration with PyCharm Professional to make it easier for you to process, store, and analyze your data!
The integration allows you to build your data and AI apps on the Databricks Data Intelligence Platform directly within PyCharm Professional, enhancing the data analytics platform with the powerful Python IDE by JetBrains. It enables you to write code quickly and easily and run it in the cloud without extra configurations, and it offers additional benefits for working with data.
Read this blog post to learn more about the integration, who it will be useful for, and what benefits it offers.
Install the Databricks plugin Watch the plugin in action What is Databricks?The Databricks Data Intelligence Platform allows your entire organization to use data and AI. It’s built on a lakehouse to provide an open, unified foundation for all data and governance, and is powered by a Data Intelligence Engine that understands the uniqueness of your data.
What is PyCharm Professional?PyCharm Professional is a leading IDE for Python and other programming languages. It allows you to write high-quality and efficient code using superior code completion, refactoring capabilities, code inspections, seamless code and project navigation, a debugger, and a wide range of integrations, including Jupyter notebooks, testing frameworks, Git, CI/CD solutions, and more – all available in one place right out of the box.
Who will the integration be useful for?Organizations and data professionals using data lakehouses, data lakes, and data warehouses via Databricks will benefit from this integration.
What benefits does the integration bring?The integration combines the most powerful capabilities of each platform, allowing you to easily build all of your data and AI applications at scale within PyCharm:
- Use PyCharm to implement software development best practices, which are essential for large codebases, such as source code control, modular code layouts, testing, and more.
- Databricks enables the use of powerful clusters, allowing you to work on projects too large for a local machine and helping you orchestrate data processing efficiently.
You can write the code for your pipelines and jobs in PyCharm, then deploy, test, and run it in real time on your Databricks cluster without any additional configurations.
Let’s dive into more details about what the PyCharm Databricks integration provides.
Connect to your cluster via PyCharmYou can connect directly to the Databricks cluster via PyCharm and monitor the process within the IDE. This allows you to check if the cluster is running, see the results of the current session’s runs, and view process outcomes along with additional details.
Run Python scripts on a remote clusterIn addition, you can run Python scripts on a remote cluster, which is particularly useful for working with big data, and view the results in the IDE.
Run Jupyter notebooks or Python scripts as workflowsAdditionally, you can run your notebook or Python scripts as a Databricks workflow and see the output in the console.
You can see the results of the runs on the Databricks platform, including the runs initiated from PyCharm.
Synchronize project files to the Databricks workspaceThe synchronization of project files with the Databricks workspace allows you to access and work with the same files in both PyCharm and Databricks workspaces. You can also schedule your notebooks and scripts and utilize other platform features for projects completed in PyCharm.
How to get startedMake sure you have the following ready to go:
- PyCharm Professional 2024.2 and further editions
- Big Data Tools Core plugin
- Databricks account
You can install the Databricks plugin either from JetBrains Marketplace or directly from within the PyCharm IDE.
Install the Databricks pluginHead over to the documentation to get step-by-step instructions on how to get started and use the plugin.
What do you think about this integration? Share your thoughts in the comments below.
Talk Python to Me: #474: Python Performance for Data Science
EuroPython: EuroPython 2024: Post Conference Feedback
Its been a month now since EuroPython 2024 took place and as the dust settles, we’ve gathered feedback from 157 attendees to understand what made this year’s event special, what challenges were faced, and how the experience can shape future EuroPythons. Whether you were there in person or followed along online, join us as we dive into the analysing the feedback!
The data we have represents around 13% of the onsite attendees and around 11% of total attendees. It is difficult to tell whether this is a representative sample as we did not collect demographic data.
Satisfaction with the conferenceAttendees were overall very satisfied with the conference, with a mean overall satisfaction rating of 4.3. Moreover, attendees were satisfied with most specific aspects of the conference, including the venue (mean = 4.6), food (mean = 4.0), and the social event (mean = 4.0). Attendees particularly liked that the conference was hosted in Prague, with the location getting a mean rating of 4.7.
Overall, the satisfaction ratings that had the strongest relationship (Spearman correlation) with overall satisfaction with the conference were the food (rs = 0.20) and the social event (rs = 0.17); however, these are still very modest correlations, indicating that other factors we did not measure were stronger drivers of satisfaction with the conference
Mean and standard deviation of ratings per conference aspectThings that people liked about the conferenceTwo of the feedback survey questions were free text which asked attendees to comment on what they did and did not like overall about the conference. Ninety-seven respondents gave positive feedback, and 92 gave negative feedback.
In order to make these easier to analyse, used a large language model to extract the topics that each attendee was talking about in their responses. This was by no means perfect, so take it as a guide rather than something totally objective (e.g., “organisation” was pretty broadly interpreted by the model).
The top topics (where at least 5 people had mentioned them in their feedback) in the “liked” feedback are listed below.
Liked topics
Number of respondents who mentioned topic
Community
37
Food
20
Organisation
19
Talks
16
Networking
14
Atmosphere
14
Venue
10
Communication
5
Location
5
We have also plotted these topics by their mentions for better understanding
With a general overview of the feedback on EuroPython 2024 in mind, let&aposs delve into specific aspects of the conference such as the food, talks, workshops, and more
Food & CateringAs noted above in the first graph, people were overall satisfied with the food. When breaking this down by dietary requirements, satisfaction varied a bit more.
Note: we have very small samples for some of these special dietary groups,Dietary requirement
Total respondents
Mean satisfaction rating
None
115
4.13
Vegetarian
23
3.82
Vegan
11
4.00
Gluten-free
2
3.50
Lactose-intolerant
4
4.00
Low-carb
2
3.50
Halal
4
3.00
Kosher
1
5.00
Other
2
2.50
Average Satisfaction with food grouped by Dietary requirementsPyLadies workshopsOnly 28 respondents indicated that they had attended at least one PyLadies workshop, so we should interpret the below findings with caution. However, mean satisfaction with the PyLadies events was high (4.43). Below is the breakdown of mean satisfaction per PyLadies event (some people attended multiple events, hence the total exceeds 28).
PyLadies event
Total respondents
Mean satisfaction rating
Wednesday evening social event
16
4.43
Self-Defense workshop
7
4.29
PyLadies lunch
16
4.38
#IAmRemarkable workshop
1
5.00
Community tutorialsOnly 8 respondents indicated that they had attended at least one of the community tutorials so unfortunately this means we cannot break down the data by tutorial. However, the overall mean satisfaction rating was high (4.0).
TalksAttendees were asked to give feedback on which talks they particularly liked, and which ones they didn&apost like. 104 attendees gave feedback on which talks they liked, and 59 gave feedback on talks they did not like.
We normalised the feedback by matching it up to the closest title, and then checking this manually. The findings are broken down below by talk level, type and track, as well as the most liked speakers.
LevelAttendees seemed to enjoy talks across all levels equally, with around 4 times more people liking versus disliking talks at each level.
Talk level
Number of talks at conference
Number of liked talks
Number of disliked talks
Average number of likes per talk
Average number of dislikes per talk
Ratio of likes to dislikes
beginner
65
138
35
2.1
0.54
3.9
intermediate
93
178
46
1.9
0.49
3.9
advanced
14
23
6
1.6
0.43
3.8
TypeBy far the most popular type of talk were long talk sessions. These talks received a lot of feedback, with 15 times more attendees saying they liked these talks versus disliking them. The keynotes were also well received, with 4 times more people mentioning liking them versus disliking them.
Posters were only mentioned once in the feedback. While it is hard to say from this feedback as it does not measure attendance, it is possible these sessions were not well attended.
Talk type
Number of talks at conference
Number of liked talks
Number of disliked talks
Average number of likes per talk
Average number of dislikes per talk
Ratio of likes to dislikes
Talk (long session)
25.0
61.0
4.0
2.4
0.16
15.2
Keynote
6.0
84.0
20.0
14
3.33
4.2
Talk
92.0
174.0
51.0
1.9
0.55
3.4
Tutorial
16.0
9.0
5.0
0.6
0.31
1.8
Sponsored
8.0
8.0
6.0
1
0.75
1.3
Conference Workshop
1.0
0.25
Panel
2.0
2.0
1
Poster
9.0
1.0
0.1
Track
While it is hard to draw robust conclusions for this category as there are very small samples in most of the tracks, some particularly popular tracks (with a high ratio of likes to dislikes and high number of overall likes) are:
- Arts, Crafts Culture & Demos
- Testing and QA
- Career, Life, Health
- Python Libraries and Tooling
- Python Internals & Ecosystem
track
Number of talks at conference
Number of liked talks
Number of disliked talks
Average number of likes per talk
Average number of dislikes per talk
Ratio of likes to dislikes
Arts, Crafts Culture & Demos
3
30
1.0
10.0
0.33
30.0
Testing and QA
5
17
1.0
3.4
0.2
17.0
Career, Life, Health
4
28
2.0
7.0
0.5
14.0
PyData: Deep Learning, NLP, CV
8
7
1.0
0.88
0.13
7.0
DevOps and Infrastructure (Cloud & Hardware)
5
13
2.0
2.6
0.4
6.5
Python Libraries & Tooling
23
49
10.0
2.13
0.43
4.9
Web technologies
9
4
1.0
0.44
0.11
4.0
Python Internals & Ecosystem
24
62
18.0
2.58
0.75
3.4
Education, Community & Diversity
7
19
7.0
2.71
1.0
2.7
PyData: LLMs
10
15
6.0
1.5
0.6
2.5
PyData: Data Engineering
10
9
4.0
0.9
0.4
2.3
Software Engineering & Architecture
14
31
14.0
2.21
1.0
2.2
Security
6
4
3.0
0.67
0.5
1.3
PyData: Machine Learning, Stats
7
3
3.0
0.43
0.43
1.0
~ None of these topics
3
1
1.0
0.33
0.33
1.0
PyData: Research & Applications
6
1
2.0
0.17
0.33
0.5
Ethics, Philosophy & Politics
1
1
1.0
PyData: Software Packages & Jupyter
5
7
1.4
Special thank you to our amazing data wizard Jodie Burchell for putting together together this report!
If you have any questions, you are welcome to reach out to the team at helpdesk@europython.eu
Gunnar Wolf: The social media my blog –as well as some other sites I publish in– is pushed to will soon stop receiving updates
For many years, I have been using the dlvr.it service to echo my online activity to where more people can follow it. Namely, I write in the following sources:
- My blog (where this content is being posted to) → RSS
- Mostly academic publications I send to my university’s repository (including conference presentations and the like) → RSS
- Videos posted to my YouTube channel (mostly my classes but some other material as well) → RSS
Via dlvr.it’s services, all those posts are “echoed” to Gwolfwolf in X (Twitter) and to the Gunnarwolfi page in Facebook. I use neither platform as a human (that is, I never log in there).
Anyway, dlvr.it sent me a mail stating they would be soon (as in, the next few weeks) cutting their free tier. And, although I value their services and am thankfulfor their value so far, I am not going to pay for my personal stuff to be reposted to social media.
So, this post’s mission is twofold:
- If you follow me via any of those media, you will soon not be following me anymore 😉
- If you know of any service that would fill the space left by dlvr.it, I will be very grateful. Extra gratefulness points if the option you suggest is able to post to accounts in less-propietary media (i.e. the Fediverse). Please tell me by mail (gwolf@gwolf.org).
Oh! Forgot to mention: Of course, my blog will continue to be appear in Planet Debian, Blografía, and any decent aggregator that consumes my RSS.
#! code: Drupal 10: An Introduction To Batch Processing With The Batch API
The Batch API is a powerful feature in Drupal that allows complex or time consuming tasks to be split into smaller parts.
For example, let's say you wanted to run a function that would go through every page on you Drupal site and perform an action. This might be removing specific authors from pages, or removing links in text, or deleting certain taxonomy terms. You might create a small loop that just loads all pages and performs the action on those pages.
This is normally fine on sites that have a small number of pages (i.e. less than 100). But what happens when the site has 10,000 pages, or a million? Your little loop will soon hit the limits of PHP execution times or memory limits and cause the script to be terminated. How do you know how far your loop progressed through the data? What happens if you tried to restart the loop?
The Batch API in Drupal solves these problems by splitting this task into parts so that rather than run a single process to change all the pages at the same time. When the batch runs a series of smaller tasks (eg. just 50 pages at a time) are progressed until the task is complete. This means that you don't hit the memory or timeout limits of PHP and the task finishes successfully and in a predictable way. Rather than run the operation in a single page request the Batch API allows the operation to be run through lots of little page request, each of which nibbles away at the task until it is complete.
This technique can be used any a variety of different situations. Many contributed modules in Drupal make use of this feature to prevent processes taking too long.
Debian Brasil: Debian Day 30 years at IF Sul de Minas, Pouso Alegre - Brazil
by Thiago Pezzo and Giovani Ferreira
Local celebrations of Debian 2024 Day also happened on [Pouso Alegre, MG, Brazil] (https://www.openstreetmap.org/relation/315431). In this year we managed to organize two days of lectures!
On the 14th of August 2024, Wednesday morning, we were on the [Federal Institute of Education, Science and Technology of the South of Minas Gerais] (https://portal.ifsuldeminas.edu.br/index.php), (IFSULDEMINAS), Pouso Alegre campus. We did an introductory presentation of the Project Debian, operating system and community, for the three years of the Technical Course in Informatics (professional high school). The event was closed to IFSULDEMINAS students and talked to 60 people.
On August 17th, 2024, a Saturday morning, we held the event open to the community at the University of the Sapucaí Valley (Univás), with institutional support of the Information Systems Course. We speak about the Debian Project with Giovani Ferreira (Debian Developer); about the Debian pt_BR translation team with Thiago Pezzo; about everyday experiences using free software with Virginia Cardoso; and on how to set up a development environment ready for production using Debian and Docker with Marcos António dos Santos. After the lectures, snacks, coffee and cake were served, while the participants talked, asked questions and shared experiences.
We would like to thank all the people who have helped us:
- Michelle Nery (IFSULDEMINAS) and André Martins (UNIVÁS) for the aid in the local organization
- Paulo Santana (Debian Brazil) by the general organization
- Virginia Cardoso, Giovani Ferreira, Marco António and Thiago Pezzo for the lectures
- And a special thanks to all of you who participated in our celebratio
Some pictures:
Debian Brasil: Debian Day 2024 em Pouso Alegre/MG - Brasil
por Thiago Pezzo e Giovani Ferreira
As celebrações locais do Dia do Debian 2024 também aconteceram em Pouso Alegre, MG, Brasil. Neste ano conseguimos organizar dois dias de palestras!
No dia 14 de agosto de 2024, quarta-feira pela manhã, estivemos no campus Pouso Alegre do Instituto Federal de Educação, Ciência e Tecnologia do Sul de Minas Gerais (IFSULDEMINAS). Fizemos a apresentação introdutória do Projeto Debian, sistema operacional e comunidade, para os três anos do Curso Técnico de Ensino Médio em Informática. O evento foi fechado para o IFSULDEMINAS e estiveram presentes por volta de 60 estudantes.
Já no dia 17 de agosto de 2024, um sábado pela manhã, realizamos o evento aberto à comunidade na Universidade do Vale do Sapucaí (Univás), com apoio institucional do Curso de Sistemas de Informação. Falamos sobre o Projeto Debian com Giovani Ferreira (Debian Developer); sobre a equipe de tradução Debian pt_BR com Thiago Pezzo; sobre experiências no dia a dia com uso de softwares livres com Virgínia Cardoso; e sobre como configurar um ambiente de desenvolvimento pronto para produção usando Debian e Docker com Marcos António dos Santos. Encerradas as palestras, foram servidos salgadinhos, café e bolo, enquanto os/as participantes conversavam, tiravam dúvidas e partilhavam experiências.
Gostaríamos de agradecer a todas as pessoas que nos ajudaram:
- Michelle Nery (IFSULDEMINAS) e André Martins (UNIVÁS) pelo auxílio na organização local
- Paulo Santana (Debian Brasil) pela organização geral
- Virgínia Cardoso, Giovani Ferreira, Marco António e Thiago Pezzo pelas palestras
- E um agradecimento especial a todas e todos que participaram da nossa comemoração!
Algumas fotos:
Mario Hernandez: SOLVED - Cannot crop based on original image after initial crop has been set
If you have read my posts about responsive images you will know I have done quite a bit of work with Drupal media and in particular, images. However, I recently ran into an issue I had not experienced before and it was quite challenging to comprehend. The issue was related to image cropping.
In our Drupal platform we allow content editors to manually crop images using a hand-full of crop types for various aspect ratios such as 1:1, 3:4, 4:3, 16:9, etc. To achieve the manual crop we use the Crop API and Image Widget Crop Drupal modules.
The issue we started noticing is that no matter the image we were using, all cropping settings were limited to a predefined aspect ratio of 1:1 or square, rather than the original image's aspect ratio. This was causing big problems for us because editors were not able to properly crop images and as a result images were rendered with odd cropping settings.
After some research, I found an issue that had been reported in the Image Widget Crop module, issue #3222406. This was exactly the issue we were having and was relieved it wasn't something unique to our platform.
Cause of the issueLooking back, I think this issue was partly of my own making, but seeing that others were experiencing the same it's also possible it was just an odd bug. Long story short, the issue was caused by using an image style with specific hard dimension, as the crop preview image, See Fig. 1 below.
You may not know this but you can change image styles for almost any image within Drupal's admin. I recently completed a lot of work around image styles within our platform and perhaps I unknowingly changed the image style used by Drupal's crop preview. I can't say for sure.
SolutionThe issue was not so much the aspect ratio used in the image style used as the crop preview, but rather the hard dimensions of the image style. These dimensions were forcing all images, regardless of their aspect ratio, to use the square aspect ratio as the starting point for cropping, rather than the original image.
The solution is to use an image style that uses the Scale image effect, as the crop preview. The Scale image effect does not require image dimensions and thus allows your cropping area to always reset to the original image.
If you read comment #5 in the issue page you will see juamerico explanation of the issue in more detail and what he did to fix it.
Steps taken to address the issue- I created a new image style called Crop preview with the Scale image effect as well as using a wide aspect ratio or crop type such as 16:9.
- I configured the Manage form display for the Image media type (admin/structure/media/manage/image/form-display), so it uses the new image style I just created. See Fig. 2 below
With the changes to the Crop preview image style, every time you crop the image you are dealing with the original image rather than an already cropped image.
In closingThe main reason for writing about this topic is so I know what to do next time I run into this issue. I hope you find this helpful.
Mario Hernandez: Migrating from Patternlab to Storybook
Building a custom Drupal theme nowadays is a more complex process than it used to be. Most themes require some kind of build tool such as Gulp, Grunt, Webpack or others to automate many of the repeatitive tasks we perform when working on the front-end. Tasks like compiling and minifying code, compressing images, linting code, and many more. As Atomic Web Design became a thing, things got more complicated because now if you are building components you need a styleguide or Design System to showcase and maintain those components. One of those design systems for me has been Patternlab. I started using Patternlab in all my Drupal projects almost ten years ago with great success. In addition, Patternlab has been the design system of choice at my place of work but one of my immediate tasks was to work on migrating to a different design system. We have a small team but were very excited about the challenge of finding and using a more modern and robust design system for our large multi-site Drupal environment.
Enter StorybookAfter looking a various options for a design system, Storybook seemed to be the right choice for us for a couple of reasons: one, it has been around for about 10 years and during this time it has matured significantly, and two, it has become a very popular option in the Drupal ecosystem. In some ways, Storybook follows the same model as Drupal, it has a pretty active community and a very healthy ecosystem of plugins to extend its core functionality.
Storybook looks very promising as a design system for Drupal projects and with the recent release of Single Directory Components or SDC, and the new Storybook module, we think things can only get better for Drupal front-end development. Unfortunately for us, technical limitations in combination with our specific requirements, prevented us from using SDC or the Storybook module. Instead, we built our environment from scratch with a stand-alone integration of Storybook 8.
INFO: At the time of our implementation, TwigJS did not have the capability to resolve SDC's namespace. It appears this has been addressed and using SDC should now be possible with this custom setup. I haven't personally tried it and therefore I can't confirm. Our process and requirementsIn choosing Storybook, we went through a rigorous research and testing process to ensure it will not only solve our immediate problems with our current environment, but it will be around as a long term solution. As part of this process, we also tested several available options like Emulsify and Gesso which would be great options for anyone looking for a ready-to-go system out of the box. Some of our requirements included:
1. No components refactoringThe first and non-negotiable requirement was to be able to migrate components from Patternlab to a new design system with the least amount of refactoring as possible. We have a decent amount of components which have been built within the last year and the last thing we wanted was to have to rebuild them again because we are switching design system.
2. A new Front-end build workflowI personally have been faithful to Gulp as a front-end build tool for as long as I can remember because it did everything I needed done in a very efficient manner. The Drupal project we maintain also used Gulp, but as part of this migration, we wanted to see what other options were out there that could improve our workflow. The obvious choice seemed to be Webpack, but as we looked closer into this we learned about ViteJS, "The Next Genration Frontend Tooling". Vite delivers on its promise of being "blazing fast", and its ecosystem is great and growing, so we went with it.
3. No more Sass in favor of PostCSSCSS has drastically improved in recent years. It is now possible with plain CSS, to do many of the things you used to be able to only do with Sass or similar CSS Preprocessor. Eliminating Sass from our workflow meant we would also be able to get rid of many other node dependencies related to Sass. The goal for this project was to use plain CSS in combination with PostCSS and one bonus of using Vite is that Vite offers PostCSS processing out of the box without additional plugins or dependencies. Ofcourse if you want to do more advance PostCSS processing you will probably need some external dependencies.
Building a new Drupal theme with StorybookLet's go over the steps to building the base of your new Drupal theme with ViteJS and Storybook. This will be at a high-level to callout only the most important and Drupal-related parts. This process will create a brand new theme. If you already have a theme you would like to use, make the appropriate changes to the instructions.
1. Setup Storybook with ViteJS ViteJS- In your Drupal project, navigate to the theme's directory (i.e. /web/themes/custom/)
- Run the following command:
- When prompted, select the framework of your choice, for us the framework is React.
- When prompted, select the variant for your project, for us this is JavaScript
After the setup finishes you will have a basic Vite project running.
Storybook- Be sure your system is running NodeJS version 18 or higher
- Inside the newly created theme, run this command:
- After installation completes, you will have a new Storybook instance running
- If Storybook didn't start on its own, start it by running:
Twig templates are server-side templates which are normally rendered with TwigPHP to HTML by Drupal, but Storybook is a JS tool. TwigJS is the JS-equivalent of TwigPHP so that Storybook understands Twig. Let's install all dependencies needed for Storybook to work with Twig.
- If Storybook is still running, press Ctrl + C to stop it
- Then run the following command:
- vite-plugin-twig-drupal: If you are using Vite like we are, this is a Vite plugin that handles transforming twig files into a Javascript function that can be used with Storybook. This plugin includes the following:
- Twig or TwigJS: This is the JavaScript implementation of the Twig PHP templating language. This allows Storybook to understand Twig.
Note: TwigJS may not always be in sync with the version of Twig PHP in Drupal and you may run into issues when using certain Twig functions or filters, however, we are adding other extensions that may help with the incompatability issues. - drupal attribute: Adds the ability to work with Drupal attributes.
- Twig or TwigJS: This is the JavaScript implementation of the Twig PHP templating language. This allows Storybook to understand Twig.
- twig-drupal-filters: TwigJS implementation of Twig functions and filters.
- html-react-parser: This extension is key for Storybook to parse HTML code into react elements.
- @modifi/vite-plugin-yaml: Transforms a YAML file into a JS object. This is useful for passing the component's data to React as args.
Update your vite.config.js so it makes use of the new extensions we just installed as well as configuring the namesapces for our components.
import { defineConfig } from "vite" import yml from '@modyfi/vite-plugin-yaml'; import twig from 'vite-plugin-twig-drupal'; import { join } from "node:path" export default defineConfig({ plugins: [ twig({ namespaces: { components: join(__dirname, "./src/components"), // Other namespaces maybe be added. }, }), // Allows Storybook to read data from YAML files. yml(), ], }) Storybook configurationOut of the box, Storybook comes with main.js and preview.js inside the .storybook directory. These two files is where a lot of Storybook's configuration is done. We are going to define the location of our components, same location as we did in vite.config.js above (we'll create this directory shortly). We are also going to do a quick config inside preview.js for handling drupal filters.
- Inside .storybook/main.js file, update the stories array as follows:
- Inside .storybook/preview.js, update it as follows:
- If Storybook is still running, press Ctrl + C to stop it
- Inside the src directory, create the components directory. Alternatively, you could rename the existing stories directory to components.
With the current system in place we can start building components. We'll start with a very simple component to try things out first.
- Inside src/components, create a new directory called title
- Inside the title directory, create the following files: title.yml and title.twig
- Inside title.yml, add the following:
- Inside title.twig, add the following:
We have a simple title component that will print a title of anything you want. The level key allows us to change the heading level of the title (i.e. h1, h2, h3, etc.), and the modifier key allows us to pass a modifier class to the component, and the url will be helpful when our title needs to be a link to another page or component.
Currently the title component is not available in storybook. Storybook uses a special file to display each component as a story, the file name is component-name.stories.jsx.
- Inside title create a file called title.stories.jsx
- Inside the stories file, add the following:
- If Storybook is running you should see the title story. See example below:
- Otherwise start Storybook by running:
With Storybook running, the title component should look like the image below:
The controls highlighted at the bottom of the title allow you to change the values of each of the fields for the title.
I wanted to start with the simplest of components, the title, to show how Storybook, with help from the extensions we installed, understands Twig. The good news is that the same approach we took with the title component works on even more complex components. Even the React code we wrote does not change much on large components.
In the next blog post, we will build more components that nest smaller components, and we will also add Drupal related parts and configuration to our theme so we can begin using the theme in a Drupal site. Finally, we will integrate the components we built in Storybook with Drupal so our content can be rendered using the component we're building. Stay tuned. For now, if you want to grab a copy of all the code in this post, you can do so below.
Resources In closingGetting to this point was a team effort and I'd like to thank Chaz Chumley, a Senior Software Engineer, who did a lot of the configuration discussed in this post. In addition, I am thankful to the Emulsify and Gesso teams for letting us pick their brains during our research. Their help was critical in this process.
I hope this was helpful and if there is anything I can help you with in your journey of a Storybook-friendly Drupal theme, feel free to reach out.
Reproducible Builds (diffoscope): diffoscope 276 released
The diffoscope maintainers are pleased to announce the release of diffoscope version 276. This version includes the following changes:
[ Chris Lamb ] * Also catch RuntimeError when importing PyPDF so that PyPDF or, crucially, its transitive dependencies do not cause diffoscope to traceback at runtime and build time. (Closes: #1078944, reproducible-builds/diffoscope#389) * Factor out a method for stripping ANSI escapes. * Strip ANSI escapes from the output of Procyon. Thanks, Aman Sharma! * Update copyright years.You find out more by visiting the project homepage.
GSoC 2024: Progress Update
I’ve added ECM as a dependency and am now using some of its modules. While this introduces the downside of adding an extra dependency, ECM is fairly common across KDE apps, so it’s reasonable to assume that most users will already have it installed on their systems.
The project now uses the KDEInstallDirs6, KDECMakeSettings, and KDECompilerSettings ECM modules, making the default build settings consistent with the rest of KDE software.
I’ve also integrated ECMAddTests, which has greatly simplified the CMakeLists file related to testing.
PImplThe classes in the library have been refactored to use the PImpl idiom, as suggested by Albert. This improves ABI compatibility and aligns with KDE’s policies regarding binary compatibility issues with C++.
TestingThe testing framework used by the library has been switched from Google Test to Qt Test. Google Test adheres strictly to some Google policies that could potentially be troublesome in the future, such as quickly dropping support for older compilers. Additionally, Qt Test seems to integrate better with KDE’s CI. For instance, Google Test failed to compile on the Android pipeline, but migrating to Qt Test completely resolved this issue without requiring any workarounds.
MankalaTo put MankalaEngine to use, I am developing a GUI, Mankala, which will offer a selection of games from the Mancala family. I’ve already started learning Qt, and developing this will be my primary focus during the remaining weeks of GSoC.
I plan to continue working on this project after GSoC concludes and eventually integrate both Mankala and MankalaEngine into KDE.
New Craft cache 24.08 published
A new Craft cache has just been published. The update is already available for KDE's CD, CI will follow in the next hours or days.
Please note that this only applies to the Qt6 cache. The Qt5 cache is in LTS mode since April 2024 and does not recieve major updates anymore.
Changes (highlights)- Qt 6.7.2
- FFmpeg 7.0.1
- llvm 18.1.8
- boost 1.86.0
- OpenSSL 3.3.1 (for Android too, which was still on 1.1.1v until recently)
- CMake 3.30.0
- Ninja 1.12.1
- Removed qt-installer-framework (Windows)
KDE Craft is an open source meta-build system and package manager. It manages dependencies and builds libraries and applications from source on Windows, macOS, Linux, FreeBSD and Android.
Learn more on https://community.kde.org/Craft or join the Matrix room #kde-craft:kde.org
This week in KDE: System Settings modernization and Wayland color management
Many folks are on vacation right now, but KDE’s tireless contributors still worked hard to bring you a number of improvements anyway, among them some nice System Settings modernization work and improvements to Wayland color management. You’ll find them mentioned below, along with various other improvements!
Notably, we’re back to only 30 15-minute Plasma bugs — the lowest level since February of this year right before Plasma 6 was launched! Essentially, having regained the level of stability we had at the end of Plasma 5 in only 6 months, we’re super well positioned to drive this even further in the coming months. With Plasma 6 offering both stability and features, who says you can’t have it all?
Notable New FeaturesPlasma’s weather widget now shows “feels like” temperatures that take into account the heat index (Ismael Asensio, Plasma 6.2.0. Link 1 and link 2):
And yes, I see that the temperature labels in the forecast view are misaligned! We’ll get that fixed. Notable UI ImprovementsLanded a redesign of System Settings’ Keyboard page to match other similar modern pages and make things easier to find (Evgeniy Chesnokov, Plasma 6.2.0. Link):
Modernized the UI for System Settings’ Thunderbolt page, which also fixed a text readability bug (Ivan Tkachenko, Plasma 6.2.0. Link):
Modernized the UI for multiple pages in System Settings that still use QtWidgets, so that they look a bit more like their more modern QML counterparts (Thomas Duckworth, Plasma 6.2.0 and KDE Gear 24.12.0, link 1, link 2, link 3, link 4, and link 5):
Discover and its System Tray icon now always agree on whether there are any updates available (Harald Sitter, Plasma 6.2.0. Link)
Weather forecasts from the Environment Canada provider now fit in the System Tray popup at its default size, so you don’t have to enlarge it (Ismael Asensio, Plasma 6.2.0. Link)
When you drag an image or other file out of a web browser window and onto the desktop or Dolphin, the drop menu now contains only relevant actions, and with better text and icons (me: Nate Graham, Frameworks 6.6. Link 1 and link 2):
Notable Bug FixesWe accidentally broke SVG wallpaper support in Plasma 6.1.4 with the fixes to Centered placement mode, so now we’ve fixed it again. Sorry about that, everyone! (Marco Martin, Plasma 6.1.5. Link)
Fixed a tricky KWin bug that caused copied text to sometimes not be paste-able into XWayland-using apps (David Edmundson, Plasma 6.2.0. Link)
Worked around a Qt issue that was causing some windows on disconnected screens to sometimes not get moved over to one of the remaining screens as expected (Xaver Hugl, Plasma 6.2.0. Link)
Addressed a few more edge cases for the bug whereby Plasma’s “Show Alternatives” popup wouldn’t close in certain circumstances, so now it should always close when needed (Niccolò Venerandi, Plasma 6.2.0. Link)
Fixed an issue that caused some symbolic icons in Plasma panels to be colored improperly with mixed light/dark global themes (Nicolas Fella, Frameworks 6.6. Link)
Other bug information of note:
- 3 Very high priority Plasma bugs (same as last week). Current list of bugs
- 30 15-minute Plasma bugs (down from 31 last week). Current list of bugs
- 89 KDE bugs of all kinds fixed over the last week. Full list of bugs
Added support for rendering intents and black point compensation to KWin’s implementation of the Wayland color management protocol, and enabled it by default so apps that also implement support for it can make use of it immediately (Xaver Hugl, Plasma 6.2.0. Link 1, link 2, and link 3)
KWin has gained support for the alpha-modifier Wayland protocol (Xaver Hugl, Plasma 6.2.0. Link)
On Wayland, you can now copy to and paste from the system clipboard while in Overview and other KWin effects (Vlad Zahorodnii, Plasma 6.2.0. Link)
Qt 6.8 changed how screen scaling affects icons, so we adapted to those changes to prevent icon blurriness everywhere for people already using Qt 6.8 (Nicolas Fella and Kai Uwe Broulik, Frameworks 6.6. Link 1, and link 2)
Human Interface GuidelinesExpanded the Text and Labels page to include some more symbols that should use real unicode glyphs rather than handmade approximations (Emir SARI, link)
Fixed a number of small typos, punctuation, and grammar issues throughout the text (John Veness, link 1, link 2, link 3, link 4, link 5)
Tweaked a bunch of text labels in Okular to be HIG-compliant by using real ellipses and unicode symbols (Emir SARI, Okular 24.12.0. Link)
KWin’s “Screen Edge” effect has been renamed to “Highlight Screen Edges and Hot Corners” for HIG-compliance and user-comprehensibility (me: Nate Graham, Plasma 6.2.0. Link)
Tweaked the text of Plasma’s critical battery level notifications and System Settings’ unsaved changes dialog to be HIG-compliant and therefore less redundant and more user-friendly (me: Nate Graham, Plasma 6.2.0. Link 1 and link 2)
…And Everything ElseThis blog only covers the tip of the iceberg! If you’re hungry for more, check out https://planet.kde.org, where you can find more news from other KDE contributors.
How You Can HelpOtherwise, visit https://community.kde.org/Get_Involved to discover other ways to be part of a project that really matters. Each contributor makes a huge difference in KDE; you are not a number or a cog in a machine! You don’t have to already be a programmer, either. I wasn’t when I got started. Try it, you’ll like it! We don’t bite! Or consider donating instead! That helps too.
2024 OSPP KDE Project Late-Stage Summary
It's been more than three weeks since the midterm summary, and the project is now nearing completion.
Currently, all the original features of Blinken have been fully implemented in the QML version. The remaining tasks involve UI adjustments, testing, and fixing potential bugs.
Over the past few weeks, I’ve been working on the following:
Integrating Blinken's LogicThe game logic of Blinken is handled by the BlinkenGame class from the original Blinken. The original code design is quite good, with most of the game logic encapsulated in this one class. The separation between the logic and the UI rendering is well done, so all I needed to do was connect the signals from this class in QML.
As for the audio playback in Blinken, the original code used the Phonon library, which is also open-source but does not support Android. Therefore, I replaced it with the QtMultimedia library, which provides cross-platform audio playback functionality.
Android Build for KF6 ApplicationsSome features of Blinken rely on libraries provided by the KF6 framework, such as KF6I18n and KF6Config. When cross-compiling to the Android platform, it's necessary to use the aarch64-linux versions of these libraries. If these libraries are not available on your system, you will encounter the following errors during compilation:
ld.lld: error: /usr/lib64/libKF6XmlGui.so.6.4.0 is incompatible with aarch64linux ld.lld: error: /usr/lib64/libKF6ConfigWidgets.so.6.4.0 is incompatible with aarch64linux ……However, the package manager on my Fedora distribution does not provide these versions. Compiling and installing them one by one from source is too cumbersome. On the advice of the community, I used Craft to handle cross-compilation.
For reference, here is the Craft tutorial: Craft - KDE Community Wiki
Important note: If you encounter installation failures, make sure to clear all contents under craft-kde-android before trying again, as leftover files may cause the installation to fail.
When installing, choose the Arm64 target architecture. If there are remnants from a previous failed installation, it may prevent the option to select the ARM64 architecture.
If you encounter issues like "Permission denied," you’ll need to disable SELinux:
sudo apt-get install selinux-utils sudo setenforce 0Additionally, note that in the virtual machine invent-registry.kde.org/sysadmin/ci-images/android-qt67 provided by the community, the Java version is outdated, preventing the use of Gradle 8.6. You can either manually update the Java version in the docker or use an older version of Gradle.
To use Craft for building applications, you need to write a script called a Blueprint, which describes the libraries your application depends on. These scripts are relatively easy to write, and you can quickly get started by following the community documentation: Craft/Blueprints - KDE Community Wiki.
Using KF6 Framework LibrariesSome of the libraries originally used by Blinken are compatible with the Android platform, while others are not. By referring to the API Documentation, you can check which libraries are supported on Android. In Blinken, the following libraries are Android-compatible:
- CoreAddons
- GuiAddons
- I18n
- XmlGui
I needed to use these libraries in the QML version of Blinken.
The KF6 framework provides a convenient internationalization API, and the usage in QML is almost the same as in QWidget, which allowed me to directly reuse Blinken’s original multi-language support, saving a lot of time.
KConfig is used in Blinken to store high score information and settings. For the high scores, I needed to extract the HighScoreManager class from the original HighScoreDialog file, make some modifications, and then create a new high score interface in QML that connects the signals and slots of HighScoreManager. For the settings functionality, it’s as simple as registering a KConfig singleton in QML :
`qmlRegisterSingletonInstance<blinkenSettings>("org.kde.blinken", 1, 0, "BlinkenSettings", blinkenSettings::self());KF6XmlGui was used in the original Blinken to create the About Blinken Page, About KDE Page, and Handbook Page. Although this library is Android-compatible, it is based on QWidget, while the main interface of Blinken is built with QML. Bringing in QWidget just for these pages didn't seem like a good idea. Luckily, for the Android platform, kirigami-addons provides this functionality. By incorporating it, I also brought in Kirigami, which helps optimize the UI.
After adding new dependencies, it’s important to modify the .kde-ci.yml file to support CI/CD. For more information: Infrastructure/Continuous Integration System - KDE Community Wiki.
Glyph Lefkowitz: On The Defense Of Heroes
If a high-status member of a community that you participate in is accused of misbehavior, you may want to defend them. You may even write a long essay in their defense.
In that essay, it may seem only natural to begin with a lengthy enumeration of the accused’s positive personal qualities. To extol the quality of their career and their contributions to your community. To talk about how nice they are. To be a character witness in the court of public opinion.
If you do this, you are not defending them. You are proving the point. This is exactly how missing stairs come to exist. People don’t get away with bad behavior if they don’t have high status and a good reputation already.
Sometimes, someone with antisocial inclinations seeks out status, in order to facilitate their bad behavior. Sometimes, a good, but, flawed person does a lot of really good work and thereby accidentally ends up with more status than they were expecting to have, and they don’t know how to handle it. In either case, bad behavior may ensue.
If you truly believe that your fave is being accused or punished unjustly, focus on the facts. What, specifically, has been alleged? How are these allegations substantiated? What verifiable evidence exists to the contrary? If you feel that someone is falsely accusing them to ruin their reputation, is there evidence to support your claim that the accusation is false? Ask yourself the question: what information do you have, that is leading to your correct analysis of the situation, that the people making the accusations do not have, which might be leading them into error?
But, also, maybe just… don’t?
The urge to defend someone like this is much more likely to come from a sense of personal grievance than justice. Consider: does it feel like you are being attacked, when your fave has been attacked? Is there a tightness in your chest, heat rising on your cheeks? Do you feel suddenly defensive?
Do you think that defensiveness is likely to lead to you making good, rational decisions about what steps to take next?
Let your heroes face accountability. If they are really worth your admiration, they might accept responsibility and make amends. Or they might fight the accusations with their own real evidence — evidence that you, someone peripheral to their situation, are unlikely to have — and prove the accusations wrong.
They might not want your defense. Even if they feel like they do want it in the moment — they are human too, after all, and facing accountability does not feel good to us humans — is the intensified feeling that they can’t let down their supporters who believe in them likely to make them feel less defensive and panicked?
In either case, your character defense is unlikely to serve them. At best it helps them stay on an ego trip, at worst it muddies the waters and might confuse the collection of facts that would, if considered dispassionately, properly exonerate them.
Do you think you think that I am speaking in generalities but really just talking about one specific recent event?
Wrong!
Just in this last week, I have read 2 different blog posts about 2 completely different people in completely unrelated communities and both of their authors need to read this. But each of those were already of a type, one that I’ve read dozens of instances of in the past.
It is a very human impulse to perceive a threat to someone we think well of, and to try to defend against that threat. But the consequences of someone’s own actions are not a threat you can defend them from.
Web Review, Week 2024-33
Let’s go for my web review for the week 2024-33.
Why We Picked AGPL - ParadeDBTags: tech, foss, business
I wish more product companies would pick this license. Going for AGPL with a support and/or double license offering is a strong model in my opinion.
https://blog.paradedb.com/pages/agpl
Tags: tech, foss, economics
Interesting initiative. I’m looking forward to the results of this first pilot.
https://www.sovereigntechfund.de/programs/fellowship
Tags: tech, google, monopoly, law, economics
Of course it sounds complicated to break Google up… but that’s not the point. It’s about avoiding its monopolistic position, the fact that it’s complicated is just another symptom.
https://micro.webology.dev/2024/08/14/breaking-up-google.html
Tags: tech, google, browser, web, standard
Yes, please let’s increase the market share of non-Chromium based browsers.
https://endler.dev/2024/the-dying-web/
Tags: tech, security, hacking
Someone was about to get revenge, this gives an interesting exploration.
https://blog.smithsecurity.biz/hacking-the-scammers
Tags: tech, cpu, amd, security
Luckily this kind of very low level vulnerabilities are not too common and difficult to exploit. But when they get exploited all things break loose and you can’t trust your hardware anymore.
https://www.wired.com/story/amd-chip-sinkclose-flaw/
Tags: tech, security, memory
Interesting take, those bugs are more convenient to exploit. Logic bugs are too specific to easily exploit at scale.
https://pacibsp.github.io/2024/why-exploits-prefer-memory-corruption.html
Tags: tech, security, ssh
Clearly a new OpenSSH feature to keep an eye on. This should improved security of the server by default. That said, it needs to be a bit more in the wild before knowing how to best tune it.
https://utcc.utoronto.ca/~cks/space/blog/sysadmin/OpenSSHPerSourcePenaltiesThings
Tags: tech, windows, networking
This is indeed surprising behavior and specific to Windows. If you wonder why TCP connect is slow and you got IPv6 support active this might be why.
https://daniel.haxx.se/blog/2024/08/14/slow-tcp-connect-on-windows/
Tags: tech, python, performance
Interesting dive into some of the performance improvements introduced into recent CPython releases.
https://blog.codingconfessions.com/p/are-function-calls-still-slow-in-python
Tags: tech, python, type-systems
Here is an interesting use of Pydantic to properly model inputs.
https://blog.yossarian.net/2024/08/12/Approximating-sum-types-in-Python-with-Pydantic
Tags: tech, c++, reflection, type-systems, performance
Compile time reflection in C++ will indeed be a big deal.
https://lemire.me/blog/2024/08/13/reflection-based-json-in-c-at-gigabytes-per-second/
Tags: tech, time, databases, sqlite
Looks like a neat extension which can come in handy.
https://antonz.org/sqlean-time/
Tags: tech, databases, postgresql, tools
Looks like an interesting tool for creating anonymized pre-production environments.
Tags: tech, databases, postgresql
Need to duplicate data in Postgres? Several options are on the table.
https://ongres.com/blog/fastest_way_copy_data_between_postgres_tables/
Tags: tech, web, browser, frontend, html
A new HTML attribute to keep an eye on. I can expect people to abuse it with hard to debug problems in the frontend if you don’t know it is there.
https://csswizardry.com/2024/08/blocking-render-why-whould-you-do-that/
Tags: tech, garbage-collector, performance, safety, memory
Interesting, it confirms garbage collectors can be the source of unrecoverable performance degradation in request based systems.
https://brooker.co.za/blog/2024/08/14/gc-metastable.html
Tags: tech, distributed, failure, recovery
Retries are becoming common place to deal with transient errors. That said, they can be a problem with recovery of longer failures due to amplification. There are options on the table to solve this though.
https://medium.com/yandex/good-retry-bad-retry-an-incident-story-648072d3cee6
Tags: tech, design, complexity, performance
Or why anticipating too much is merely a gamble. You can be lucky, but how often will you be? Also I agree that in such cases the performance will be impacted longer term leading to a death by thousands of paper cuts.
https://www.sebastiansylvan.com/post/the-perils-of-future-coding/
Tags: tech, technical-debt, organization, leadership, funny
I’m not sure the incentives are right… it’s better to clean up as you go. Still some places would benefit from such an event from time to time and even if you clean up as you go missed opportunities happen.
https://zaidesanton.substack.com/p/organizing-the-best-cleanathon-your
Tags: tech, organization
Surprisingly, I bumped into this article as I’m wrapping up reading the Team Topologies book. This highlight fairly well some of the concerns I have with it and where it shines. I think it’s right to turn to the principles it’s built on rather than use the model it proposes as a blueprint.
https://martyoo.medium.com/stop-team-topologies-fd954ea26eca
Tags: business, organization, management, strategy
It’s bloody hard to build a strategy. This article is full of good wisdom to make one. This won’t make it really easier, but at least you won’t start in the wrong direction and will be able to know if what you produce is any good.
https://www.cultivatedmanagement.com/how-to-build-a-strategy/
Tags: tech, blender, 3d, funny
Funny short video, I guess it has also some tutorial value to know what you can do with Blender? (and no, you can’t break the fourth wall with it)
https://www.youtube.com/watch?v=gTi_-HGtsDY
Bye for now!
mark.ie: My LocalGov Drupal contributions for week-ending August 16th, 2024
Here's what I've been working on for my LocalGov Drupal contributions this week. Thanks to Big Blue Door for sponsoring the time to work on these.
Dries Buytaert: Drupal CMS: the official name for Drupal Starshot
We're excited to announce that "Drupal CMS" will be the official name for the product developed by the Drupal Starshot Initiative.
The name "Drupal CMS" was chosen after user testing with both newcomers and experienced users. This name consistently scored highest across all tested groups, including marketers unfamiliar with Drupal.
Participants appreciated the clarity it brings:
Having the words CMS in the name will make it clear what the product is. People would know that Drupal was a content management system by the nature of its name, rather than having to ask what Drupal is. I'm a designer familiar with the industry, so the term CMS or content management system is the term or phrase that describes this product most accurately in my opinion. I think it is important to have CMS in the title.The name "Drupal Starshot" will remain an internal code name until the first release of Drupal CMS, after which it will most likely be retired.
Dries Buytaert: Evolving Drupal's Layout Builder to an Experience Builder
Imagine a world where installing Drupal instantly offers a creative experience that allows you to build and style pages right out of the box, without any need for additional modules or configuration.
The introduction of Drupal's Layout Builder in 2018 was an important milestone toward this vision, but it was just the first step. Layout Builder provides site builders with a powerful drag-and-drop interface for creating and arranging content within customizable layouts.
Despite its success, there is a clear and pressing need to improve the existing Layout Builder. The numerous community-developed modules enhancing Layout Builder highlight the need for a more comprehensive solution.
That is why at DrupalCon Lille last year, I was excited to announce the "Next Generation Page Builder" initiative, aimed at improving and expanding the Layout Builder to provide a truly intuitive, out-of-the-box page-building experience.
Since announcing the 'Next Generation Page Builder', led by Lauri Eskola (Acquia), a Drupal Core Committer, we've done extensive research and planning.
Inspired by user feedback, we decided to make two changes. First, we decided to broaden our focus: not only will we improve the page-building features of Layout Builder, we will also integrate basic theming capabilities, enabling users to style their pages effortlessly without having to edit Twig files. Second, reflecting on this wider scope, we renamed the initiative from 'Next Generation Page Builder' to 'Experience Builder'.
In recent months, we explored several options for how to create such an Experience Builder, including accelerating development of the Layout Builder, switching to Gutenberg, adopting Paragraphs, or using the newly open-sourced Plasmic.
After thorough analysis and discussions with key stakeholders, including Automattic's Gutenberg team, the Drupal Core Committers decided the best approach is to expand the Layout Builder while also incorporating the best elements of Paragraphs.
Looking to the future, I hope the Experience Builder becomes the preferred Drupal tool for layout design, page building, and basic theming. Our main goal is to create a tool that site builders love, with an amazing out-of-the-box experience. By integrating key features from Paragraphs, we also aim to create a unified solution that reduces fragmentation, accelerates innovation, and ensures Drupal remains at the forefront of site building.
Our future success hinges on expanding Drupal's usability to a wider audience. Our CMS capabilities are often better than our competitors', but aren't always as user friendly. In the Drupal 7 era, Drupal was the OG (Original Great) of low-code but today we are being outpaced by competitors in terms of ease of use. Without user experience improvements, we'll lose ground. The Experience Builder initiative is all about introducing more people to the power of Drupal.
I feel strongly that a unified Experience Builder is one of the most important initiatives we can undertake right now.
Developing an Experience Builder is a big task that will require substantial effort, extensive collaboration, and significant expertise in user experience and design. As Drupal Core Committers, we are driven by a sense of urgency to advance this initiative. We are committed to moving quickly and iterating rapidly, but to succeed, we also need your support. There will be many opportunities for the community to collaborate and contribute to this initiative.
For more information, please check Lauri's latest blog post on the topic. Additionally, I will discuss this further in my upcoming DrupalCon Portland keynote in a few weeks.
mark.ie: My Drupal Core Contributions for week-ending August 16th, 2024
Here's what I've been working on for my Drupal contributions this week. Thanks to Code Enigma for sponsoring the time to work on these.