FLOSS Project Planets

Droptica: Curious about Drupal 7 to 11 migration costs? Collect all the info for estimation in 5 minutes

Planet Drupal - Mon, 2024-09-30 05:48

Migrating from Drupal 7 to the latest version, like Drupal 11, might seem like a big challenge, but it doesn’t have to be. One of the most common obstacles is figuring out how much it will cost. You want to know the price, but you don’t want to give full access to your site just to get an estimate. The good news? You can collect all the necessary information for an accurate project estimate in just 5 minutes.

Categories: FLOSS Project Planets

The Drop Times: Non-Code Contributions Shine at DrupalCon Barcelona 2024

Planet Drupal - Mon, 2024-09-30 04:26
Reporting from DrupalCon Barcelona, Esmeralda Tijhoff highlights the growing focus on non-code contributions. From event organizing to marketing, the sessions underscored the crucial role non-coders play in shaping Drupal's future. Find out how you can contribute to the community without writing a single line of code!
Categories: FLOSS Project Planets

Python Bytes: #403 A machine learning algorithm walks into a bar…

Planet Python - Mon, 2024-09-30 04:00
<strong>Topics covered in this episode:</strong><br> <ul> <li><strong><a href="https://simonwillison.net/2024/Sep/8/uv-under-discussion-on-mastodon/?featured_on=pythonbytes">uv under discussion on Mastodon</a></strong></li> <li><strong><a href="https://github.com/drivendataorg/erdantic?featured_on=pythonbytes">erdantic: Entity Relationship Diagrams</a></strong></li> <li><strong>Extra, Extra, Extra</strong></li> <li><strong>Django Extra, Extra, Extra</strong></li> <li><strong>Extras</strong></li> <li><strong>Joke</strong></li> </ul><a href='https://www.youtube.com/watch?v=nqVZVvXcOps' style='font-weight: bold;'data-umami-event="Livestream-Past" data-umami-event-episode="403">Watch on YouTube</a><br> <p><strong>About the show</strong></p> <p>Sponsored by us! Support our work through:</p> <ul> <li>Our <a href="https://training.talkpython.fm/?featured_on=pythonbytes"><strong>courses at Talk Python Training</strong></a></li> <li><a href="https://courses.pythontest.com/p/the-complete-pytest-course?featured_on=pythonbytes"><strong>The Complete pytest Course</strong></a></li> <li><a href="https://www.patreon.com/pythonbytes"><strong>Patreon Supporters</strong></a></li> </ul> <p><strong>Connect with the hosts</strong></p> <ul> <li>Michael: <a href="https://fosstodon.org/@mkennedy"><strong>@mkennedy@fosstodon.org</strong></a></li> <li>Brian: <a href="https://fosstodon.org/@brianokken"><strong>@brianokken@fosstodon.org</strong></a></li> <li>Show: <a href="https://fosstodon.org/@pythonbytes"><strong>@pythonbytes@fosstodon.org</strong></a></li> </ul> <p>Join us on YouTube at <a href="https://pythonbytes.fm/stream/live"><strong>pythonbytes.fm/live</strong></a> to be part of the audience. Usually <strong>Monday</strong> at 10am PT. Older video versions available there too.</p> <p>Finally, if you want an artisanal, hand-crafted digest of every week of the show notes in email form? Add your name and email to <a href="https://pythonbytes.fm/friends-of-the-show">our friends of the show list</a>, we'll never share it.</p> <p><strong>Michael #1:</strong> <a href="https://simonwillison.net/2024/Sep/8/uv-under-discussion-on-mastodon/?featured_on=pythonbytes">uv under discussion on Mastodon</a></p> <ul> <li>It’s interesting that uv is slightly controversial</li> <li><p><a href="https://cloudisland.nz/@freakboy3742/113093889194737339?featured_on=pythonbytes">Russell</a>:</p></li> <li><p>As enthusiastic as I am about the direction uv is going, I <em>haven't</em> adopted them anywhere - because I want very much to understand Astral’s intended business model before I hook my wagon to their tools.</p></li> <li><p><a href="https://mastodon.social/@hynek/113094437303343866?featured_on=pythonbytes">Hynek</a>:</p></li> <li><p>As much as I hate VC, [...] FOSS projects flame out all the time too. … To me uv looks like a genius sting to trick VCs into paying to fix packaging. We’ll be better off either way.</p></li> <li><p><a href="https://mastodon.social/@glyph/113094489295782200?featured_on=pythonbytes">Glyph</a>:</p></li> <li><p>Rust is more expensive and difficult to maintain, not to mention "non-native" to the average customer here. … it can burn out <em>all</em> the other projects in the ecosystem simultaneously, creating a risk of monoculture</p></li> <li><p><a href="https://mastodon.social/@hynek/113094547139925962?featured_on=pythonbytes">Hynek on Rust</a>:</p></li> <li><p>I don’t think y’all quite grok what uv makes so special due to your seniority. The speed is really cool, but the reason Rust is elemental is that it’s one compiled blob that can be used to bootstrap and maintain a Python development.</p></li> <li><p><a href="https://social.coop/@chrisjrn/113094511860843571?featured_on=pythonbytes">Christopher Neugebauer</a>:</p></li> <li><p>Just dropping in here to say that corporate capture of the Python ecosystem is the #1 keeps-me-up-at-night subject in my community work, so I watch Astral with interest, even if I'm not yet too worried.</p></li> <li><p><a href="https://lucumr.pocoo.org/2024/8/21/harvest-season/?featured_on=pythonbytes">Armin Ronacher</a></p></li> <li><p>What uv is doing, even in the worst possible future this is a very forkable and maintainable thing.</p></li> <li><p>Finally, see the comment at the end by Charlie Marsh</p></li> </ul> <p><strong>Brian #2:</strong> <a href="https://github.com/drivendataorg/erdantic?featured_on=pythonbytes">erdantic: Entity Relationship Diagrams</a></p> <ul> <li>“erdantic is a simple tool for drawing entity relationship diagrams (ERDs) for Python data model classes. Diagrams are rendered using the venerable Graphviz library.”</li> <li>Supported data modeling frameworks are: <ul> <li>Pydantic V2</li> <li>Pydantic V1 legacy</li> <li>attrs</li> <li>dataclasses </li> </ul></li> </ul> <p><strong>Michael #3:</strong> <strong>Extra, Extra, Extra</strong></p> <ul> <li>Added <a href="https://search.pythonbytes.fm/api/browser">Python Bytes Search as a custom search engine</a>.</li> <li><a href="https://mkennedy.codes/posts/passkey-great-but-careful-of-the-lock-in/?featured_on=pythonbytes">Along came passkeys. A cool idea that quickly turned evil.</a></li> <li>Follow up from post and my conversation last week: <a href="https://github.com/dani-garcia/vaultwarden?featured_on=pythonbytes">vaultwarden</a> (via <a href="https://x.com/mkennedy/status/1838974519463334163?featured_on=pythonbytes">Pablo</a>)</li> <li><a href="https://github.com/astral-sh/uv/releases/tag/0.4.16?featured_on=pythonbytes">uv publish</a></li> <li>Trying the <a href="https://help.vivaldi.com/desktop/tabs/tab-display/?featured_on=pythonbytes">tabs on bottom lifestyle</a> inspired by Arc</li> <li>Adding <a href="https://search.pythonbytes.fm/api/browser">Python Bytes</a> (and Talk Python) <a href="https://mkennedy.codes/posts/you-should-use-custom-search-engines-way-more/?featured_on=pythonbytes">as custom search engines</a>.</li> <li><a href="https://www.python.org/events/python-events/1507/?featured_on=pythonbytes">PyCon 2025 dates</a>: From 14 May through 22 May, 2025</li> </ul> <p><strong>Brian #4:</strong> Django Extra, Extra, Extra</p> <ul> <li><a href="https://blog.jetbrains.com/pycharm/2024/09/django-project-ideas/?featured_on=pythonbytes">Django Project Ideas</a> <ul> <li>Evgenia Verbina</li> <li>Project ideas with list of tech stack stuff you’ll learn and/or work on with the project</li> <li>Ex: Recipe organizer <ul> <li>tech stack: Django templates, Django ORM, Optional JavaScript</li> <li>“Familiarize yourself with Django’s ORM (object-relational mapper) and database support by building an app to keep track of your favorite recipes. Add a web-based frontend with options to filter recipes by category, ingredients, and user ratings so you can easily browse for inspiration.”</li> </ul></li> </ul></li> <li><a href="https://djangotv.com?featured_on=pythonbytes">DjangoTV</a> <ul> <li>Jeff Triplett</li> <li>Django conference videos and tutorials.</li> </ul></li> <li><a href="https://github.com/django-commons?featured_on=pythonbytes">Django Commons</a> <ul> <li>Heard about from Lacey Henschel</li> <li>“Django Commons is an organization dedicated to supporting the community's efforts to maintain packages. It seeks to improve the maintenance experience for all contributors; reducing the barrier to entry for new contributors and reducing overhead for existing maintainers.”</li> </ul></li> <li><a href="https://docs.djangoproject.com/en/5.1/releases/5.0/#simplified-templates-for-form-field-rendering">Django 5 has simplified templates for better form field rendering</a></li> <li>But if you want a completely different take on forms, maybe try <a href="https://docs.iommi.rocks/en/latest/forms.html?featured_on=pythonbytes">iommi forms</a> <ul> <li>They wrote about it on <a href="https://kodare.net/2024/09/11/why-we-wrote-a-new-form-library-for-django.html?featured_on=pythonbytes">Why we wrote a new form library for Django</a></li> </ul></li> <li><a href="https://adamj.eu/tech/2024/09/26/django-introducing-djade/?featured_on=pythonbytes">Djade: a Django template formatter</a> <ul> <li>Adam Johnson</li> <li>Like black or ruff, but for Django templates.</li> </ul></li> </ul> <p><strong>Extras</strong> </p> <p>Brian:</p> <ul> <li><a href="https://liamwhite.dev/posts/0035-hostile-source-environment?featured_on=pythonbytes"><strong>The Open Source Project Maintainer's Guide</strong></a> <ul> <li>Suggested by Rafael Weingartner</li> </ul></li> </ul> <p><strong>Joke:</strong> <a href="https://devhumor.com/media/a-machine-learning-algorithm-walks-into-a-bar?featured_on=pythonbytes">A Machine Learning algorithm walks into a bar…</a></p>
Categories: FLOSS Project Planets

eGenix.com: Python Meeting Düsseldorf - 2024-10-02

Planet Python - Mon, 2024-09-30 04:00

The following text is in German, since we're announcing a regional user group meeting in Düsseldorf, Germany.

Ankündigung

Das nächste Python Meeting Düsseldorf findet an folgendem Termin statt:

02.10.2024, 18:00 Uhr
Raum 1, 2.OG im Bürgerhaus Stadtteilzentrum Bilk
Düsseldorfer Arcaden, Bachstr. 145, 40217 Düsseldorf


Programm Bereits angemeldete Vorträge
  • Detlef Lannert:
    pyinfra als Alternative zu Ansible
  • Marc-André Lemburg:
    Rapid web app development with Panel
  • Detlef Lannert:
    Low-cost-Objekte als Alternativen zu Dictionaries?
  • Charlie Clark:
    Editieren von ZIP Dateien mit Python
Weitere Vorträge können gerne noch angemeldet werden. Bei Interesse, bitte unter info@pyddf.de melden. Startzeit und Ort

Wir treffen uns um 18:00 Uhr im Bürgerhaus in den Düsseldorfer Arcaden.

Das Bürgerhaus teilt sich den Eingang mit dem Schwimmbad und befindet sich an der Seite der Tiefgarageneinfahrt der Düsseldorfer Arcaden.

Über dem Eingang steht ein großes "Schwimm’ in Bilk" Logo. Hinter der Tür direkt links zu den zwei Aufzügen, dann in den 2. Stock hochfahren. Der Eingang zum Raum 1 liegt direkt links, wenn man aus dem Aufzug kommt.

>>> Eingang in Google Street View

⚠️ Wichtig: Bitte nur dann anmelden, wenn ihr absolut sicher seid, dass ihr auch kommt. Angesichts der begrenzten Anzahl Plätze, haben wir kein Verständnis für kurzfristige Absagen oder No-Shows. Einleitung

Das Python Meeting Düsseldorf ist eine regelmäßige Veranstaltung in Düsseldorf, die sich an Python Begeisterte aus der Region wendet.

Einen guten Überblick über die Vorträge bietet unser PyDDF YouTube-Kanal, auf dem wir Videos der Vorträge nach den Meetings veröffentlichen.

Veranstaltet wird das Meeting von der eGenix.com GmbH, Langenfeld, in Zusammenarbeit mit Clark Consulting & Research, Düsseldorf:

Format

Das Python Meeting Düsseldorf nutzt eine Mischung aus (Lightning) Talks und offener Diskussion.

Vorträge können vorher angemeldet werden, oder auch spontan während des Treffens eingebracht werden. Ein Beamer mit HDMI und FullHD Auflösung steht zur Verfügung.

(Lightning) Talk Anmeldung bitte formlos per EMail an info@pyddf.de

Kostenbeteiligung

Das Python Meeting Düsseldorf wird von Python Nutzern für Python Nutzer veranstaltet.

Da Tagungsraum, Beamer, Internet und Getränke Kosten produzieren, bitten wir die Teilnehmer um einen Beitrag in Höhe von EUR 10,00 inkl. 19% Mwst. Schüler und Studenten zahlen EUR 5,00 inkl. 19% Mwst.

Wir möchten alle Teilnehmer bitten, den Betrag in bar mitzubringen.

Anmeldung

Da wir nur 25 Personen in dem angemieteten Raum empfangen können, möchten wir bitten, sich vorher anzumelden.

Meeting Anmeldung bitte per Meetup

Weitere Informationen

Weitere Informationen finden Sie auf der Webseite des Meetings:

              https://pyddf.de/

Viel Spaß !

Marc-Andre Lemburg, eGenix.com

Categories: FLOSS Project Planets

Zato Blog: Enterprise Python: Integrating with Salesforce

Planet Python - Mon, 2024-09-30 03:43
Enterprise Python: Integrating with Salesforce 2024-09-30, by Dariusz Suchojad Overview

Salesforce connections are one of the newest additions to Zato 3.2, allowing you to look up and manage Salesforce records and other business data. To showcase it, the article will create a sample Salesforce marketing campaign in a way that does not require the usage of anything else except for basic REST APIs combined with plain Python objects, such as dicts.

If you have not done it already, you can download Zato here.

Basic workflow

The scope of our works will be:

  • Creating Salesforce credentials for our integration project
  • Defining a Salesforce connection in Zato
  • Authoring a service that will map input data to the format that Salesforce expects
  • Creating a Zato REST channel that will be invoked through curl during tests
  • Testing the integration
Creating Salesforce credentials

To be able to create as connection to Salesforce in the next step, we need a few credentials. There is a full article about how to prepare them and this section is the gist of it.

In runtime, based on this information, Zato will obtain the necessary authentication and authorization tokens itself, which means that you will only focus on the business side of the integrations, not on the low-level aspects of it.

The process of obtaining the credentials needs to be coordinated with an administrator of your organization. To assist in that, the screenshots below explain where to find them.

The credentials are:

  • Username and password
  • Consumer key
  • Consumer secret

The username and password are simply the same credentials that can be used to log in to Salesforce:

Consumer key and secret are properties of a connected app - this is a term that Salesforce uses for API clients that invoke its services. If you are already an experienced Salesforce REST API user, you may know the key and secret under their aliases of "client_id" and "client_secret" - these are the same objects.

Note that when a connected app already exists and you would like to retrieve the key and secret, they will be available under the "View" menu option for the app, not under "Edit" or "Manage".

Defining a Salesforce connection in Zato

With all the credentials in place, we can create a new Salesforce connection in Zato Dashboard, as below.

Authoring an integration service in Python

Above, we created a connection definition that lets Zato obtain session tokens and establish connections to Salesforce. Now, we can create an API service that will make use of such connections.

In the example below, we are using the POST REST method to invoke an endpoint that creates new Salesforce campaigns. In your own integrations, you can invoke any other Salesforce endpoint, using any REST method as needed, by following the same pattern, which is, create a model with input fields, build a Python dict for the request to Salesforce, invoke it and map all the required from the response from Salesforce to that which your own service returns to its own callers.

Note that we use a datamodel-based SimpleIO definition for the service. Among other things, although we are not going to do it here, this would let us offer definitions for this and other services.

# -*- coding: utf-8 -*- # stdlib from dataclasses import dataclass # Zato from zato.server.service import Model, Service # ########################################################################### if 0: from zato.server.connection.salesforce import SalesforceClient # ########################################################################### @dataclass(init=False) class CreateCampaignRequest(Model): name: str segment: str # ########################################################################### @dataclass(init=False) class CreateCampaignResponse(Model): campaign_id: str # ########################################################################### class CreateCampaign(Service): class SimpleIO: input = CreateCampaignRequest output = CreateCampaignResponse def handle(self): # This is our input data input = self.request.input # type: CreateCampaignRequest # Salesforce REST API endpoint to invoke - note that Zato # will add a prefix to it containing the API version. path = '/sobjects/Campaign/' # Build the request to Salesforce based on what we received request = { 'Name': input.name, 'Segment__c': input.segment, } # .. create a reference to our connection definition .. salesforce = self.cloud.salesforce['My Salesforce Connection'] # .. obtain a client to Salesforce .. with salesforce.conn.client() as client: # type: SalesforceClient # .. create the campaign now .. sf_response = client.post(path, request) # .. build our response object .. response = CreateCampaignResponse() response.campaign_id = sf_response['id'] # .. and return its ID to our caller. self.response.payload = response # ########################################################################### Creating a REST channel

Note that we assign HTTP Basic Auth credentials to the channel. In this manner, it is possible for clients of this REST channel to authenticate using a method that they are already familiar which simplifies everyone's work - it is Zato that deals with how to authenticate against Salesforce whereas your API clients use the ubiquitous HTTP Basic Auth method.

Testing

The last step is to invoke the newly created channel:

$ curl http://api:password@localhost:17010/api/campaign/create -d '{"name":"Hello", "segment":"123"}' {"campaign_id":"8901Z3VHXDTebEJWs"} $

That is everything - you have just integrated with Salesforce and exposed a REST channel for external applications to integrate with!

More resources

➤ Python API integration tutorial
What is an integration platform?
Python Integration platform as a Service (iPaaS)
What is an Enterprise Service Bus (ESB)? What is SOA?

More blog posts
Categories: FLOSS Project Planets

Quansight Labs Blog: Numpy QuadDType: Quadruple Precision for Everyone

Planet Python - Sun, 2024-09-29 20:00
Introducing the new data-type for Numpy providing cross-platform support of quadruple precision.
Categories: FLOSS Project Planets

Quansight Labs Blog: Polars Plugins: let's make them easier to use

Planet Python - Sun, 2024-09-29 20:00
Increasing ease-of-use of Polars plugins by improving an existing tutorial.
Categories: FLOSS Project Planets

Python⇒Speed: Beyond multi-core parallelism: faster Mandelbrot with SIMD

Planet Python - Sun, 2024-09-29 20:00

What do you do when computation is too expensive?

Recently I’ve had a brilliant business idea: Mandelbrot-as-a-Service! Instead of companies calculating their own fractals, I will do it for them, freshly calculated in the cloud, with no work on their part. And by using cloud computing, I will be able to scale to the no-doubt vast number of customers who will be paying for my ingenious new service.

I have two goals:

  1. Speeding up results: The faster I can return fractals, the happier my customers will be.
  2. Reducing costs: If I can pay my cloud provider less for computing, my profits will go up!

Unfortunately, since I will only be selling freshly calculated and warm-from-the-CPU Mandelbrots, I can’t rely on caching.

What would you do in this situation?

One obvious approach is parallelism: threading or multiprocessing. This will speed up results, so it’s definitely worth doing, but it won’t reduce my costs. If we use 10 cores instead of 1 core, the service will return results ten times faster, but we’ll have to pay approximately 10× as much, since we’ll be using 10× larger instances.

However, if we can figure out how to speed up calculations on a single core, this will contribute to both our goals. We’ll both get faster results, compounded by any multi-core processing, and reduce compute costs.

In this article we will:

  • Quickly go over a standard Mandelbrot implementation, written in Rust.
  • Discuss why it can be tricky to optimize the Mandelbrot algorithm on a single CPU core.
  • Demonstrate how you can in fact do so, by using masked SIMD operations.
  • Trivially add on multi-core parallelism, using Rust’s Rayon library.
  • PROFIT!
Read more...
Categories: FLOSS Project Planets

Liip: DrupalCon Barcelona Recap

Planet Drupal - Sun, 2024-09-29 18:00

DrupalCon Barcelona Group picture by Bram Driesen (source)

Hola de nou barcelona

Barcelona for me has a long history of Drupal. For Drupal Dev Days 2012 I organized a mapping sprint, we cycled to DrupalCon Barcelona 2015 as part of the #tourdedrupal report , pictures and it was nice to visit a more local event - Drupal Summer - in 2016 (report, pictures).

Coding beyond functionality. Altering technologies through artistic research by Mónica Rikić Drupal CMS: una nova experiència immediata per a Drupal

This year, the focus was on Drupal CMS (previously known by its internal development name Starshot) which is all about bringing Drupal to the next level by creating an out-of-the-box experience including a new way to create layouts (Experience Builder), integrating AI features and many more features. If you like to dive deeper into Drupal CMS, check out the meta issue listing all work tracks as well as the landing page on Drupal.org.

Driesnote by Dries Buytaert

A similar, prepackaged version of Drupal already exists, handcrafted by many individuals and agencies. Recipes have recently been introduced to Drupal core. They allow to package configuration and content to pre-configure Drupal for common use cases like Search, SEO-optimization or an Event calendar feature.

Check out our blökkli starterkit that provides you will a fully-preconfigured setup that we use at Liip.

DrupalCon Crowd Drupal al govern

We saw Drupal's wide adoption for Government at DrupalCon Barcelona.

Implementing AI solutions for the French government - in this session it was demonstrated how public services were improved. AI technology would support the public servants by pregenerating responses that would be validated and modified by the public servant. The use of AI technology cut down response times from an average of 19 days to 3 days and a plus of 11% found the received answers helpful. 

Running a fleet of web sites with ease via LocalGov Drupal Microsites Platform showed a feature that we are also planning to roll out to one of our customers soon. You can easily manage multiple microsites in Drupal and configure on a per-site-basis the needed styling options in order to customize it to each site needs. By leveraging one CMS basis, the time-to-market and total cost of ownership for each microsite can be heavily reduced.

Jonathan Noack & Thom Nagy presenting about bs.ch

Large-scale content creation with Drupal — Delights, Pitfalls and support structures to help editors - in this session our customer Thom Nagy & our product owner Jonathan Noack presented their case study on relaunching bs.ch. I liked to see how a trustful collaboration with strong communication and stakeholder management combined with agile delivery and innovation led to an outcome all participants are proud about.

The website is our flagship showcase for blökkli, the interactive pagebuilder that has delighted many of our customers already and is available for the community under the open-source license.

Even though the canton is embedded in a typically restrictive government environment, they even launched the first AI-based assistant "Alva" that answers any questions the public might have about the canton in their own language using GPT-based technology.

Sostenibilitat

Conferences that bring together folks from all over the world have a hard time being sustainable. I appreciate the efforts to promote sustainable transport for example when amongst the attendees traveling by train, a winner was selected.

The organizing team also worked with the sponsors to make sure they were taking sustainability into account for how they set up their booths and limit the swag they would give out to participants.

DrupalCon Barcelona Mascot watching the crowd

The next DrupalCon Europe has been announced to happen in Vienna October 14-17 2025. I am particularly excited for this location as I grew up in Vienna and have been part of the Drupal Austria community as an organizing member before moving to Switzerland.

As Vienna is at the heart of Europe, I encourage you to think about sustainable ways to get to the conference.

If you travel via Hamburg, Bregenz/Feldkirch, Roma/Blorence/Bologna or Amsterdam, you should even be able to sleep on one of the new generation nightrains that offers better comfort, single-cabins and wheelchair-accessible sleepers. You typically can book your train 6 months ahead. As they introduced dynamic pricing recently, it is recommended to book your tickets early.

The beach alongside DrupalCon Barcelona

I leave you with some pictures from this year in Barcelona

Would you like to learn more about Drupal? Find an event near you. See you 2025 at one of my favorites Drupal Mountain Camp in Davos or at DrupalCon Vienna.

Categories: FLOSS Project Planets

Web Wash: How to Organize Content Entity Forms in Drupal

Planet Drupal - Sun, 2024-09-29 16:27

Drupal provides a robust framework for creating and managing content. However, managing form fields in complex content entities can be challenging. The Field Group, Inline Entity Form, and Conditional Fields modules offer practical tools for improving the user experience and streamlining the content creation process.

In the above live stream, we’ll use all three modules to organize and clean up fields on an “Event” content type.

Below are the show notes for the live stream.

Categories: FLOSS Project Planets

#! code: Drupal 11: Using The Batch API To Process CSV Files

Planet Drupal - Sun, 2024-09-29 15:01

This is the fourth article in a series of articles about the Batch API in Drupal. The Batch API is a system in Drupal that allows data to be processed in small chunks in order to prevent timeout errors or memory problems.

So far in this series we have looked at creating a batch process using a form, followed by creating a batch class so that batches can be run through Drush and then using the finished state to control batch processing. All of these articles go together to form a basis of batch processing in Drupal.

In this article we will look at bringing these concepts together to perform a task that is quite common on websites, processing Comma Separated Value or CSV files, which we will do using the Drupal Batch API.

Processing CSV data is very common on the web. Whilst it is quite common to integrate with an API it is sometimes simpler to just generate a CSV file of the data you need from one system and upload it into a form on a website. Most systems will allow you to export data as a CSV file of some kind, but it's also very easy to export a CSV from commonly used programs like Excel and Google Sheets.

Processing a CSV file in PHP is quite simple, but once you reach one hundred records you will find that PHP will start to throw errors due to timeouts or memory issues. The solution is to employ the Batch API to spread the load of that processing over a number of different requests.

Read more

Categories: FLOSS Project Planets

Open Source Conferences in September

Planet KDE - Sun, 2024-09-29 14:00

After having participated to both Qt Contributor Summit and Akademy, I ended up going to a few more conferences in September.

Nextcloud Conference

I went to Nextcloud Conference just after going back from Akademy. Unfortunately I was quite tired from Akademy and Qt Contributor Summit and I only stayed Saturday morning. Still it was great to meet some old colleagues there.

Group photo of the Nextcloud conference

Matrix Conference

The Matrix Conference happened the weekend after the Nextcloud conference. This was the first Matrix Conference and a gathering of all types of actors involved in Matrix. From the grassroots community to companies deploying Matrix based solutions to their customers. The NeoChat team was there and we were super productive into bringing back the Android version, thanks to the help of Volker Krause. This resulted in many patches in NeoChat itself but also one patch in Kirigami.

Special mention to the food and coffee offered at the conference, which was always excellent and either vegan or vegetarian. Outside of the venue, food was also execellent with a lot of middle eastern food choice.

Here some photos of the event and the food:

Donuts Hacking at the conference venue Hacking at C-Base Food outside of the venue Linux Days Dornbirn

It was my second time going to the Linux Days in Dornbirn and while the weather wasn’t as welcoming as last time, the local Linux community was again super welcoming!

During the event, I did a talk in German about Plasma 6. This was my first time doing a talk in German and I hope I did okay. I also hosted a KDE stand with Simon Österle, who offered his help with the stand. His help has been invaluable to me, so huge thanks to him.

Like last year, after the conference, all helpers, presenters and stand holders went to a local restaurent to enjoy Käsespätzle. It was again delicious.

Here some photos of the event and the food:

Banner at the entrance of the Linux Days Steam Deck and Plasma Mobile The new KDE Banner Linux Days dinner menu Käsespätzle Apfelstrudel Bodensee on the way to Austria Bodensee from the train on the way back A script element has been removed to ensure Planet works properly. Please find it in the original post. A script element has been removed to ensure Planet works properly. Please find it in the original post.
Categories: FLOSS Project Planets

Conferences in September

Planet KDE - Sun, 2024-09-29 14:00

After having participated to both Qt Contributor Summit and Akademy, I ended up going to a few more conferences in September.

Nextcloud Conference

I went to Nextcloud Conference just after going back from Akademy. Unfortunately I was quite tired from Akademy and Qt Contributor Summit and I only stayed Saturday morning. Still it was great to meet some old colleagues there.

Group photo of the Nextcloud conference

Matrix Conference

The Matrix Conference happened the weekend after the Nextcloud conference. This was the first Matrix Conference and a gathering of all types of actors involved in Matrix. From the grassroots community to companies deploying Matrix based solutions to their customers. The NeoChat team was there and we were super productive into bringing back the Android version, thanks to the help of Volker Krause. This resulted in many patches in NeoChat itself but also one patch in Kirigami.

Special mention to the food and coffee offered at the conference, which was always excellent and either vegan or vegetarian. Outside of the venue, food was also execellent with a lot of middle eastern food choice.

Here some photos of the event and the food:

Donuts Hacking at the conference venue Hacking at C-Base Food outside of the venue Linux Days Dornbirn

It was my second time going to the Linux Days in Dornbirn and while the weather wasn’t as welcoming as last time, the local Linux community was again super welcoming!

During the event, I did a talk in German about Plasma 6. This was my first time doing a talk in German and I hope I did okay. I also hosted a KDE stand with Simon Österle, who offered his help with the stand. His help has been invaluable to me, so huge thanks to him.

Like last year, after the conference, all helpers, presenters and stand holders went to a local restaurent to enjoy Käsespätzle. It was again delicious.

Here some photos of the event and the food:

Banner at the entrance of the Linux Days Steam Deck and Plasma Mobile The new KDE Banner Linux Days dinner menu Käsespätzle Apfelstrudel Bodensee on the way to Austria Bodensee from the train on the way back A script element has been removed to ensure Planet works properly. Please find it in the original post. A script element has been removed to ensure Planet works properly. Please find it in the original post.
Categories: FLOSS Project Planets

This Week in KDE Apps

Planet KDE - Sun, 2024-09-29 10:30
New KCron Settings UI, Krita 2.2.5 released, and more

Welcome to the third post in our “This Week in KDE Apps” series! If you missed it, we just announced this new series two weeks ago, and our goal is to cover as much as possible of what's happening in the KDE world and complete Nate's This Week in Plasma.

This week we had new releases of Amarok and Krita. There is also news regarding KDE Connect, the link between all your devices; Kate, the KDE advanced text editor; Itinerary, the travel assistant that lets you plan all your trips; Marble, KDE's map application; and more.

Let's get started!

Amarok

Amarok 3.1.1 was released. 3.1.1 features a number of small improvements and bug fixes, including miscellaneous fixes for toolbars and the return of tag dialog auto-completions — functionality that initially got lost during the Qt5/KF5 port. However, most of the work has again happened under the hood to improve the codebase's Qt6/KF6 compatibility.

See the full announcement for more information

Itinerary

Itinerary now supports search for places (e.g. street names) in addition to stops. (Code: Jonah Brüchert, Icon: Mathis Brüchert, 24.12.0. Link)

Itinerary now shows the date of the connection when searching for a public transport connection. (Jonah Brüchert, 24.12.0. Link 1, link 2)

Digikam

A new face detection algorithm based on YuNet is now available. (Michael Miller, Link)

Kate

The debug plugin now works on Windows! (Waqar Ahmed, 24.12.0. Link)

The debug plugin is now much more usable. (Waqar Ahmed, 24.12.0. Link 1, link 2, link 3)

Kate context menu will now show relevant external tools. (Waqar Ahmed, 24.12.0. Link)

KCron

The System Settings page was ported to QML and given a fancy new UI! (Evgeny Chesnokov, 24.12.0. Link)

KDE Connect

Fixed the Bluetooth support for KDE Connect. (Rob Emery, 24.12.0. Link 1, link 2)

Keysmith

Keysmith now has an "About" page. (Plata Hill, 24.12.0. Link)

Kleopatra

Kleopatra now supports OpenPGP v5 keys. (Ingo Klöcker, 24.12.0. Link 1, link 2)

Krita

Krita 5.2.5 was released and is bringing over 50 bugfixes since 5.2.3 (5.2.4 was a Windows-specific hotfix). Major fixes have been done to audio playback, transform mask calculation and more! Read more.

LabPlot

LabPlot implements a new type of plot: Process Behavior Chart (X-Chart), (Alexander Semke, Link)

Marble

Marble Maps, the QML version of Marble, has a new icon. (Mathis Brüchert, 24.12.0. Link)

Fixed a major source of visual glitches in the QML version of Marble when looking at the Earth globe. (Carl Schwan, 24.08.2. Link)

Marble Behaim — a special version of Marble to look at the oldest globe representation of the Earth known to exist — now also works on desktop thanks to Kirigami, and all the additional information and credits are now displayed using a standard "About" page. (Carl Schwan, 24.12.0. Link)

Marble's KRunner integration, Plasma Widget and the Wallpaper plugin are now fully ported to Plasma 6. (Carl Schwan, 24.12.0. Link)

NeoChat

On modern versions of Android, NeoChat will now request the correct permission to send system notifications. (James Graham, 24.12.0. Link)

Spectacle

Spectacle now respects your custom save file format as expected when using the "Save As" functionality. (Noah Davis, 24.08.2. Link)

Others

Valentyn Bondarenko updated several screenshots of KDE apps:

Eamonn Rea made more Kirigami applications remember their size across launches:

…And Everything Else

This blog only covers the tip of the iceberg! If you’re hungry for more, check out Nate's blog about Plasma and KDE's Planet, where you can find more news from other KDE contributors.

Get Involved

The KDE organization has become important in the world, and your time and contributions have helped achieve that status. As we grow, it’s going to be equally important that your support become sustainable.

We need you for this to happen. You can help KDE by becoming an active community member and getting involved. Each contributor makes a huge difference in KDE; you are not a number or a cog in a machine! You don’t have to be a programmer, either. There are many things you can do: you can help hunt and confirm bugs, even maybe solve them; contribute designs for wallpapers, web pages, icons and app interfaces; translate messages and menu items into your own language; promote KDE in your local community; and a ton more things.

You can also help us by donating. Any monetary contribution, however small, will help us cover operational costs, salaries, travel expenses for contributors and in general help KDE continue bringing Free Software to the world.

Categories: FLOSS Project Planets

Mike C. Fletcher: Interesting Memory Leak with Python 3.12 for PyOpenGL-accelerate

Planet Python - Sun, 2024-09-29 10:18

So I'm currently trying to figure out why the PyOpenGL 3.12 test suite is failing. There's a particular test that looks for VBO memory leakage and it looks loosely like this:
for i in range(100):
create_a_vbo_and_delete_it()
calculate_total_process_memory()
assert_no_leak()

which shouldn't ever lose more than a few bytes (limit is set to 200 for this test, but it doesn't lose even one normally). This passes fine on python2.7 through 3.11, but on 3.12 the first 75 iterations leak nothing, then on the 76th iteration (always the 76th) iteration there is a substantial memory leak (100s of KB) and then memory usage goes flat again.

My first guess is that there's something in the 3.12 JIT compiler that looks for e.g. 75 iterations, then does lots of analysis and caching and uses the 100s of KBs of RAM to track the behaviour. I can "fix" the test by reducing the iterations below 75, but that doesn't really address the underlying issue of the test, which is that it's using whole-system memory as a proxy for "did this local function leak RAM". Guess I need to find a better "does some RAM leak" test.

Update: always 75th iteration observation is *only* when run with just the single test. When run in the main test suite, the JIT seems to kick in much earlier (likely because of other tests exercising the same paths). That means it's likely to start failing as more tests are added, which reinforces the need to find a better test method.

Categories: FLOSS Project Planets

Drupal life hack's: Drupal Link Generation: Comparing link_generator, renderer, and Url Methods

Planet Drupal - Sun, 2024-09-29 09:55
Drupal Link Generation: Comparing link_generator, renderer, and Url Methods admin Sun, 09/29/2024 - 16:55
Categories: FLOSS Project Planets

Amarok 3.1.1 released

Planet KDE - Sun, 2024-09-29 05:40

The Amarok Development Squad is happy to announce the immediate availability of Amarok 3.1.1, the first bugfix release for Amarok 3.1 "Tricks of the Light"!

3.1.1 features a number of small improvements and bug fixes, including miscellaneous fixes for toolbars and the return of tag dialog autocompletions, a functionality that initially got lost during the Qt5/KF5 port. However, most of the work has again happened under the hood to improve the codebase's Qt6/KF6 compatibility. For the 3.2 version coming up later this year, the KDE frameworks dependency will be raised to 5.108. This should allow replacing the remaining deprecated KF5 functionalities; one of the final barriers preventing Qt6/KF6 based builds from succeeding.

Changes since 3.1.0 CHANGES:
  • Most of the context view QML items ported from QtControls 1 to QtControls 2
  • Default to no fadeout on pause and stop (BR 491603)
BUGFIXES:
  • Actually show the file browser panel toolbar
  • Fix track editor autocompletions (BR 491520)
  • Ensure home icon is shown in browser breadcrumb widgets (BR 491354)
Getting Amarok

In addition to source code, Amarok is available for installation from many distributions' package repositories, which are likely to get updated to 3.1.1 soon, as well as the flatpak available on flathub.

Packager section

You can find the tarball package on download.kde.org and it has been signed with Tuomas Nurmi's GPG key.

Categories: FLOSS Project Planets

Vasudev Kamath: Signing the systemd-boot on Upgrade Using Dpkg Triggers

Planet Debian - Sun, 2024-09-29 03:38

In my previous post on enabling SecureBoot, I mentioned that one pending improvement was signing the systemd-boot EFI binary with my keys on every upgrade. In this post, we'll explore the implementation of this process using dpkg triggers.

For an excellent introduction to dpkg triggers, refer to this archived blog post. The source code mentioned in that post can be downloaded from alioth archive.

From /usr/share/doc/dpkg/spec/triggers.txt, triggers are described as follows:

A dpkg trigger is a facility that allows events caused by one package but of interest to another package to be recorded and aggregated, and processed later by the interested package. This feature simplifies various registration and system-update tasks and reduces duplication of processing.

To implement this, we create a custom package with a single script that signs the systemd-boot EFI binary using our key. The script is as simple as:

#!/bin/bash set -e echo "Signing the new systemd-bootx64.efi" sbsign --key /etc/secureboot/db.key --cert /etc/secureboot/db.crt \ /usr/lib/systemd/boot/efi/systemd-bootx64.efi echo "Invoking bootctl install to copy stuff" bootctl install

Invoking bootctl install is optional if we have enabled systemd-boot-update.service, which will update the signed bootloader on the next boot.

We need to have a triggers file under the debian/ folder of the package, which declares its interest in modifications to the path /usr/lib/systemd/boot/efi/systemd-bootx64.efi. The trigger file looks like this:

# trigger 1 interest on systemd-bootx64.efi interest-noawait /usr/lib/systemd/boot/efi/systemd-bootx64.efi

You can read about various directives and their meanings that can be used in the triggers file in the deb-triggers man page.

Once we build and install the package, this request is added to /var/lib/dpkg/triggers/File. See the screenshot below after installation of our package:

To test the functionality, I performed a re-installation of the systemd-boot-efi package, which provides the EFI binary for systemd-boot, using the following command:

sudo apt install --reinstall systemd-boot-efi

During installation, you can see the debug message being printed in the screenshot below:

To test the systemd-boot-update.service, I commented out the bootctl install line from the above script, performed a reinstallation, and restarted the systemd-boot-update.service. Checking the log, I saw the following:

Sep 29 13:42:51 chamunda systemd[1]: Stopping systemd-boot-update.service - Automatic Boot Loader Update... Sep 29 13:42:51 chamunda systemd[1]: Starting systemd-boot-update.service - Automatic Boot Loader Update... Sep 29 13:42:51 chamunda bootctl[1801516]: Skipping "/efi/EFI/systemd/systemd-bootx64.efi", same boot loader version in place already. Sep 29 13:42:51 chamunda bootctl[1801516]: Skipping "/efi/EFI/BOOT/BOOTX64.EFI", same boot loader version in place already. Sep 29 13:42:51 chamunda bootctl[1801516]: Skipping "/efi/EFI/BOOT/BOOTX64.EFI", same boot loader version in place already. Sep 29 13:42:51 chamunda systemd[1]: Finished systemd-boot-update.service - Automatic Boot Loader Update. Sep 29 13:43:37 chamunda systemd[1]: systemd-boot-update.service: Deactivated successfully. Sep 29 13:43:37 chamunda systemd[1]: Stopped systemd-boot-update.service - Automatic Boot Loader Update. Sep 29 13:43:37 chamunda systemd[1]: Stopping systemd-boot-update.service - Automatic Boot Loader Update...

Indeed, the service attempted to copy the bootloader but did not do so because there was no actual update to the binary; it was just a reinstallation trigger.

The complete code for this package can be found here.

With this post the entire series on using UKI to Secureboot with Debian comes to an end. Happy hacking!.

Categories: FLOSS Project Planets

Mario Hernandez: Automating your Drupal Front-end with ViteJS

Planet Drupal - Sat, 2024-09-28 21:31

Modern web development relies heavily on automation to stay productive, validate code, and perform repetitive tasks that could slow developers down. Front-end development in particular has evolved, and it can be a daunting task to configure effective automation. In this post, I'll try to walk you through basic automation for your Drupal theme, which uses Storybook as its design system.

Recently I worked on a large Drupal project that needed to migrate its design system from Patternlab to Storybook. I knew switching design systems also meant switching front-end build tools. The obvious choice seemed to be Webpack, but as I looked deeper into build tools, I discovered ViteJS.

Vite is considered the Next Generation Frontend Tooling, and when tested, we were extremely impressed not only with how fast Vite is, but also with its plugin's ecosystem and its community support. Vite is relatively new, but it is solid and very well maintained. Learn more about Vite.

The topics covered in this post can be broken down in two categories:

  1. Preparing the Front-end environment

  2. Automating the environment

1. Build the front-end environment with Vite & Storybook

In a previous post, I wrote in detail how to build a front-end environment with Vite and Storybook, I am going to spare you those details here but you can reference them from the original post.

  1. In your command line, navigate to the directory where you wish to build your environment. If you're building a new Drupal theme, navigate to your site's web/themes/custom/
  2. Run the following commands (Storybook should launch at the end):
npm create vite@latest storybook cd storybook npx storybook@latest init --type react

Fig. 1: The first command builds the Vite project, and the last one integrates Storybook into it.

Reviewing Vite's and Storybook's out of the box build scripts

Vite and Storybook ship with a handful of useful scripts. We may find some of them already do what we want or may only need minor tweaks to make them our own.

  • In your code editor, open package.json from the root of your newly built project.
  • Look in the scripts section and you should see something like this:
"scripts": { "dev": "vite", "build": "vite build", "lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0", "preview": "vite preview", "storybook": "storybook dev -p 6006", "build-storybook": "storybook build" },

Fig. 2: Example of default Vite and Storybook scripts out of the box.

To run any of those scripts, prefix them with npm run. For example: npm run build, npm run lint, etc. Let's review the scripts.

  • dev: This is a Vite-specific command which runs the Vite app we just build for local development
  • build: This is the "do it all" command. Running npm run build on a project runs every task defined in the build configuration we will do later. CI/CD runners run this command to build your app for production.
  • lint: Will lint your JavaScript code inside .js or .jsx files.
  • preview: This is also another Vite-specific command which runs your app in preview mode.
  • storybook: This is the command you run to launch and keep Storybook running while you code.
  • build-storybook: To build a static version of Storybook to package it or share it, or to run it as a static version of your project.
Building your app for the first time Getting a consistent environment

In front-end development, it is important everyone in your team use the same version of NodeJS while working in the same project. This ensures consistency in your project's behavior for everyone in your team. Differences in the node version your team uses can lead to inconsistencies when the project is built. One way to ensure your team is using the same node version when working in the same project, is by adding a .nvmrc file in the root of your project. This file specifies the node version your project uses. The node version is unique to each project, which means different projects can use different node versions.

  • In the root of your theme, create a file called .nvmrc (mind the dot)
  • Inside .nvmrc add the following: v20.14.0
  • Stop Storybook by pressing Ctrl + C in your keyboard
  • Build the app:
nvm install npm install npm run build

Fig. 3: Installs the node version defined in .nvmrc, then installs node packages, and finally builds the app.

NOTE: You need to have NVM installed in your system to execute nvm commands.
You only need to run nvm install once per project unless the node version changes. If you switch to a project that uses a different node version, when you return to this project, run nvm use to set your environment back to the right node version.

The output in the command line should look like this:

Fig. 4: Screenshot of files compiled by the build command.

By default, Vite names the compiled files by appending a random 8-character string to the original file name. This works fine for Vite apps, but for Drupal, the libraries we'll create expect for CSS and JS file names to stay consistent and not change. Let's change this default behavior.

  • First, install the glob extension. We'll use this shortly to import multiple CSS files with a single import statement.
npm i -D glob
  • Then, open vite.config.js in your code editor. This is Vite's main configuration file.
  • Add these two imports around line 3 or directly after the last import in the file
import path from 'path'; import { glob } from 'glob';
  • Still in vite.config.js, replace the export default... with the following snippet which adds new settings for file names:
export default defineConfig({ plugins: [ ], build: { emptyOutDir: true, outDir: 'dist', rollupOptions: { input: glob.sync(path.resolve(__dirname,'./src/**/*.{css,js}')), output: { assetFileNames: 'css/[name].css', entryFileNames: 'js/[name].js', }, }, }, })

Fig. 5: Build object to modify where files are compiled as well as their name preferences.

  • First we imported path and { glob }. path is part of Vite and glob was added by the extension we installed earlier.
  • Then we added a build configuration object in which we defined several settings:
    • emptyOutDir: When the build job runs, the dist directory will be emptied before the new compiled code is added.
    • outDir: Defines the App's output directory.
    • rollupOptions: This is Vite's system for bundling code and within it we can include neat configurations:
      • input: The directory where we want Vite to look for CSS and JS files. Here's where the path and glob imports we added earlier are being used. By using src/**/**/*.{css,js}, we are instructing Vite to look three levels deep into the src directory and find any file that ends with .css or .js.
      • output: The destination for where CSS and JS will be compiled into (dist/css and dist/js), respectively. And by setting assetFileNames: 'css/[name].css', and entryFileNames: 'css/[name].js', CSS and JS files will retain their original names.

Now if we run npm run build again, the output should be like this:

Fig. 6: Screenshot of compiled code using the original file names.

The random 8-character string is gone and notice that this time the build command is pulling more CSS files. Since we configured the input to go three levels deep, the src/stories directory was included as part of the input path.

2. Restructure the project

The out of the box Vite project structure is a good start for us. However, we need to make some adjustments so we can adopt the Atomic Design methodology. This is today's standards and will work well with our Component-driven Development workflow. At a high level, this is the current project structure:

> .storybook/ > dist/ > public/ > src/ |- stories/ package.json vite.config.js

Fig. 7: Basic structure of a Vite project listing only the most important parts.

  • > .storybook is the main location for Storybook's configuration.
  • > dist is where all compiled code is copied into and where the production app looks for all code.
  • > public is where we can store images and other static assets we need to reference from our site. Equivalent to Drupal's /sites/default/files/.
  • > src is the directory we work out of. We will update the structure of this directory next.
  • package.json tracks all the different node packages we install for our app as well as the scripts we can run in our app.
  • vite.config.js is Vite's main configuration file. This is probably where we will spend most of our time.
Adopting the Atomic Design methodology

The Atomic Design methodology was first introduced by Brad Frost a little over ten years ago. Since then it has become the standard for building web projects. Our environment needs updating to reflect the structure expected by this methodology.

  • First stop Storybook from running by pressing Ctrl + C in your keyboard.
  • Next, inside src, create these directories: base, components, and utilities.
  • Inside components, create these directories: 01-atoms, 02-molecules, 03-organisms, 04-layouts, and 05-pages.
  • While we're at it, delete the stories directory inside src, since we won't be using it.
NOTE: You don't need to use the same nomenclature as what Atomic Design suggests. I am using it here for simplicity. Update Storybook's stories with new paths

Since the project structure has changed, we need to make Storybook aware of these changes:

  • Open .storybook/main.js in your code editor
  • Update the stories: [] array as follows:
stories: [ "../src/components/**/*.mdx", "../src/components/**/*.stories.@(js|jsx|mjs|ts|tsx)", ],

Fig. 8: Updating stories' path after project restructure.

The Stories array above is where we tell Storybook where to find our stories and stories docs, if any. In Storybook, stories are the components and their variations.

Add pre-built components

As our environment grows, we will add components inside the new directories, but for the purpose of testing our environment's automation, I have created demo components.

  • Download demo components (button, title, card), from src/components/, and save them all in their content part directories in your project.
  • Feel free to add any other components you may have built yourself. We'll come back to the components shortly.
3. Configure TwigJS

Before we can see the newly added components, we need to configure Storybook to understands the Twig and YML code we are about to introduce within the demo components. To do this we need to install several node packages.

  • In your command line run:
npm i -D vite-plugin-twig-drupal @modyfi/vite-plugin-yaml twig twig-drupal-filters html-react-parser
  • Next, update vite.config.js with the following configuration. Add the snippet below at around line 5:
import twig from 'vite-plugin-twig-drupal'; import yml from '@modyfi/vite-plugin-yaml'; import { join } from 'node:path';

Fig. 9: TwigJS related packages and Drupal filters function.

The configuration above is critical for Storybook to understand the code in our components:

  • vite-plugin-twig-drupal, is the main TwigJS extension for our project.
  • Added two new imports which are used by Storybook to understand Twig:
    • vite-plugin-twig-drupal handles transforming Twig files into JavaScript functions.
    • @modyfi/vite-plugin-yaml let's us pass data and variables through YML to our Twig components.
Creating Twig namespaces
  • Still in vite.config.js, add the twig and yml() plugins to add Twig namespaces for Storybook.
plugins: [ twig({ namespaces: { atoms: join(__dirname, './src/components/01-atoms'), molecules: join(__dirname, './src/components/02-molecules'), organisms: join(__dirname, './src/components/03-organisms'), layouts: join(__dirname, './src/components/04-layouts'), pages: join(__dirname, './src/components/05-pages'), }, }), yml(), ],

Fig. 10: Twig namespaces reflecting project restructure.

Since we removed the react() function by using the snippet above, we can remove import react from '@vitejs/plugin-react' from the imports list as is no longer needed.

With all the configuration updates we just made, we need to rebuild the project for all the changes to take effect. Run the following commands:

npm run build npm run storybook

The components are available but as you can see, they are not styled even though each component contains a CSS stylesheet in its directory. The reason is Storybook has not been configured to find the component's CSS. We'll address this shortly.

4. Configure postCSS

What is PostCSS? It is a JavaScript tool or transpiler that turns a special PostCSS plugin syntax into Vanilla CSS.

As we start interacting with CSS, we need to install several node packages to enable functionality we would not have otherwise. Native CSS has come a long way to the point that I no longer use Sass as a CSS preprocessor.

  • Stop Storybook by pressing Ctrl + C in your keyboard
  • In your command line run this command:
npm i -D postcss postcss-import postcss-import-ext-glob postcss-nested postcss-preset-env
  • At the root of your theme, create a new file called postcss.config.js, and in it, add the following:
import postcssImport from 'postcss-import'; import postcssImportExtGlob from 'postcss-import-ext-glob'; import postcssNested from 'postcss-nested'; import postcssPresetEnv from 'postcss-preset-env'; export default { plugins: [ postcssImportExtGlob(), postcssImport(), postcssNested(), postcssPresetEnv({ stage: 4, }), ], };

Fig. 11: Base configuration for postCSS.

One cool thing about Vite is that it comes with postCSS functionality built in. The only requirement is that you have a postcss.config.js file in the project's root. Notice how we are not doing much configuration for those plugins except for defining them. Let's review the code above:

  • postcss-import the base for importing CSS stylesheets.
  • postcss-import-ext-glob to do bulk @import of all CSS content in a directory.
  • postcss-nested to unwrap nested rules to make its syntax closer to Sass.
  • postcss-preset-env defines the CSS browser support level we need. Stage 4 means we want the "web standards" level of support.
5. CSS and JavaScript configuration

The goal here is to ensure that every time a new CSS stylesheet or JS file is added to the project, Storybook will automatically be aware and begin consuming their code.

NOTE: This workflow is only for Storybook. In Drupal we will use Drupal libraries in which we will include any CSS and JS required for each component.

There are two types of styles to be configured in most project, global styles which apply site-wide, and components styles which are unique to each component added to the project.

Global styles
  • Inside src/base, add two stylesheets: reset.css and base.css.
  • Copy and paste the styles for reset.css and base.css.
  • Inside src/utilities create utilities.css and in it paste these styles.
  • Inside src/, create a new stylesheet called styles.css.
  • Inside styles.css, add the following imports:
@import './base/reset.css'; @import './base/base.css'; @import './utilities/utilities.css';

Fig. 12: Imports to gather all global styles.

The order in which we have imported our stylesheets is important as the cascading order in which they load makes a difference. We start from reset to base, to utilities.

  • reset.css: A reset stylesheet (or CSS reset) is a collection of CSS rules used to clear the browser's default formatting of HTML elements, removing potential inconsistencies between different browsers before any of our styles are applied.
  • base.css: CSS Base applies a style foundation for HTML elements that is consistent for baseline styles such as typography, branding and colors, font-sizes, etc.
  • utilities.css: Are a collection of pre-defined CSS rules we can apply to any HTML element. Rules such as variables for colors, font size, font color, as well as margin, sizes, z-index, animations, etc.
Component styles

Before our components can be styled with their unique and individual styles, we need to make sure all our global styles are loaded so the components can inherit all the base/global styles.

  • Inside src/components create a new stylesheet, components.css. This is where we are going to gather all components styles.
  • Inside components.css add glob imports for each of the component's categories:
@import-glob './01-atoms/**/*.css'; @import-glob './02-molecules/**/*.css';

Fig. 13: Glob import for all components of all categories.

NOTE: Since we only have Atoms and Molecules to work with, we are omitting imports for 03-organisms, 04-layouts, 05-pages. Feel free to add them if you have that kind of components. Updating Storybook's Preview

There are several ways in which we can make Storybook aware of our styles and javascript. We could import each component's stylesheet and javascript into each *.stories.js file, but this could result in some components with multiple sub-components having several CSS and JS imports. In addition, this is not an automated system which means we need to manually do imports as they become available. The approach we are going to take is importing the stylesheets we created above into Storybook's preview system. This provides a couple of advantages:

  • The component's *.stories.js files are clean without any css imports as all CSS will already be available to Storybook.
  • As we add new components with individual stylesheets, these stylesheets will automatically be recognized by Storybook.

Remember, the order in which we import the styles makes a difference. We want all global and base styles to be imported first, before we import component styles.

  • In .storybook/preview.js add these imports at the top of the page around line 2.
import Twig from 'twig'; import drupalFilters from 'twig-drupal-filters'; import '../src/styles.css'; /* Contains reset, base, and utilities styles. */ import '../src/components/components.css'; /* Contains all components CSS. */ function setupFilters(twig) { twig.cache(); drupalFilters(twig); return twig; } setupFilters(Twig);

Fig. 14: Importing all styles, global and components.

In addition to importing two new extensions: twig and twig-drupal-filters, we setup a setupFilters function for Storybook to read Drupal filters we may use in our components. We are also importing two of the stylesheets we created earlier:

  • styles.css contains all the CSS code from reset.css, base.css, and utilities.css (in that order)
  • components.css contains all the CSS from all components. As new components are added and they have their own stylesheets, they will automatically be included in this import.
IMPORTANT: For Storybook to immediately display changes you make in your CSS, the imports above need to be from the src directory and not dist. I learned this the hard way. JavaScript compiling

On a typical project, you will find that the majority of your components don't use JavaScript, and for this reason, we don't need such an elaborate system for JS code. Importing the JS files in the component's *.stories.js should work just fine. Since the demo components dont use JS, I have commented near the top of card.stories.js how the component's JS file would be imported if JS was needed.

If the need for a more automated JavaScript processing workflow arose, we could easily repeat the same CSS workflow but for JS.

Build the project again

Now that our system for CSS and JS is in place, let's build the project to ensure everything is working as we expect it.

npm run build npm run storybook

You may notice that now the components in Storybook look styled. This tells us our new system is working as expected. However, the Card component, if you used the demo components, is missing an image. We will address this issue in the next section.

This concludes the preparation part of this post. The remaining part will focus on creating automation tasks for compiling, minifying and linting code, copying static assets such as images, and finally, watching for code changes as we code. 6. Copying images and other assets

Copying static assets like images, icons, JS, and other files from src into dist is a common practice in front-end projects. Vite comes with built-in functionality to do this. Your assets need to be placed in the public directory and Vite will automatically copy them on build. However, sometimes we may have those assets alongside our components or other directories within our project.

In Vite, there are many ways to accomplish any task, in this case, we will be using a nice plugin called vite-plugin-static-copy. Let's set it up.

  • If Storybook is running, kill it with Ctrl + C in your keyboard
  • Next, install the extension by running:
npm i -D vite-plugin-static-copy
  • Next, right after all the existing imports in vite.config.js, import one more extension:
import { viteStaticCopy } from 'vite-plugin-static-copy';
  • Lastly, still in vite.config.js, add the viteStaticCopy function configuration inside the plugins:[] array:
viteStaticCopy({ targets: [ { src: './src/components/**/*.{png,jpg,jpeg,svg,webp,mp4}', dest: 'images', }], }),

Fig. 15: Adds tasks for copying JavaScript and Images from src to dist.

The viteStaticCopy function we added allows us to copy any type of static assets anywhere within your project. We added a target array in which we included src and dest for the images we want copied. Every time we run npm run build, any images inside any of the components, will be copied into dist/images.
If you need to copy other static assets, simply create new targets for each.

  • Build the project again:
npm run build npm run storybook

The missing image for the Card component should now be visible, see below. Pretty sweet! 🍰

Fig. 16: Screenshot of the Card component in Storybook.

7. The Watch task

A watch task makes it possible for developers to see the changes they are making as they code, and without being interrupted by running commands. Depending on your configuration, a watch task watches for any changes you make to CSS, JavaScript and other file types, and upon saving those changes, code is automatically compiled, and a Hard Module Reload (HMR) is evoked, making the changes visible in Storybook.

Although there are extensions to create watch tasks, we will stick with Storybook's out of the box watch functionality because it does everything we need. In fact, I have used this very approach on a project that supports over one hundred sites.

I actually learned this the hard way, I originally was importing the key stylesheets in .storybook/preview.js using the files from dist. This works to an extend because the code is compiled upon changes, but Storybook is not aware of the changes unless we restart Storybook. I spent hours debugging this issue and tried so many other options, but at the end, the simple solution was to import CSS and JS into Storybook's preview using the source files. For example, if you look in .storybook/preview.js, you will see we are importing two CSS files which contain all of the CSS code our project needs:

import '../src/styles.css'; import '../src/components/components.css';

Fig. 17: Importing source assets into Storybook's preview.

Importing source CSS or JS files into Storybook's preview allows Storybook to become aware immediately of any code changes.

The same, or kind of the same works for JavaScript. However, the difference is that for JS, we import the JS file in the component's *.stories.js, which in turn has the same effect as what we've done above for CSS. The reason for this is that typically not every component we build needs JS.

A real watch task

Currently we are running npm run storybook as a watch task. Nothing wrong with this. However, to keep up with standards and best practices, we could rename the storybook command, watch, so we can run npm run watch. Something to consider.

You could also make a copy of the storybook command and name it watch and add additional commands you wish to run with watch, while leaving the original storybook command intact. Choices, choices.

8. Linting CSS and JavaScript

Our workflow is coming along nicely. There are many other things we can do but for now, we will end with one last task: CSS and JS linting.

  • Install the required packages. There are several of them.
npm i -D eslint stylelint vite-plugin-checker stylelint-config-standard stylelint-order stylelint-selector-pseudo-class-lvhfa
  • Next, after the last import in vite.config.js, add one more:
import checker from 'vite-plugin-checker';
  • Then, let's add one more plugin in the plugins:[] array:
checker({ eslint: { lintCommand: 'eslint "./src/components/**/*.{js,jsx}"', }, stylelint: { lintCommand: 'stylelint "./src/components/**/*.css"', }, }),

Fig. 18: Checks for linting CSS and JavaScript.

So we can execute the above checks on demand, we can add them as commands to our app.

  • In package.json, within the scripts section, add the following commands:
"eslint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0", "stylelint": "stylelint './src/components/**/*.css'",

Fig. 19: Two new npm commands to lint CSS and JavaScript.

  • We installed a series of packages related to ESLint and Stylelint.
  • vite-plugin-checker is a plugin that can run TypeScript, VLS, vue-tsc, ESLint, and Stylelint in worker thread.
  • We imported vite-plugin-checker and created a new plugin with two checks, one for ESLint and the other for Stylelint.
  • By default, the new checks will run when we execute npm run build, but we also added them as individual commands so we can run them on demand.
Configure rules for ESLint and Stylelint

Both ESLint and Stylelint use configuration files where we can configure the various rules we want to enforce when writing code. The files they use are eslint.config.js and .stylelintrc.yml respectively. For the purpose of this post, we are only going to add the .stylelintrc.yml in which we have defined basic CSS linting rules.

  • In the root of your theme, create a new file called .stylelintrc.yml (mind the dot)
  • Inside .stylelintrc.yml, add the following code:
extends: - stylelint-config-standard plugins: - stylelint-order - stylelint-selector-pseudo-class-lvhfa ignoreFiles: - './dist/**' rules: at-rule-no-unknown: null alpha-value-notation: number color-function-notation: null declaration-empty-line-before: never declaration-block-no-redundant-longhand-properties: null hue-degree-notation: number import-notation: string no-descending-specificity: null no-duplicate-selectors: true order/order: - - type: at-rule hasBlock: false - custom-properties - declarations - unspecified: ignore disableFix: true order/properties-alphabetical-order: error plugin/selector-pseudo-class-lvhfa: true property-no-vendor-prefix: null selector-class-pattern: null value-keyword-case: - lower - camelCaseSvgKeywords: true ignoreProperties: - /^--font/

Fig. 20: Basic CSS Stylelint rules.

The CSS rules above are only a starting point, but should be able to check for the most common CSS errors.

Test the rules we've defined by running either npm run build or npm run stylelint. Either command will alert you of a couple of errors our current code contains. This tells us the linting process is working as expected. You could test JS linting by creating a dummy JS file inside a component and writing bad JS in it.

9. One last thing

It goes without saying that we need to add storybook.info.yml and storybook.libraries.yml files for this to be a true Drupal theme. In addition, we need to create the templates directory somewhere within our theme.

storybook.info.yml

The same way we did for Storybook, we need to create namespaces for Drupal. This requires the Components module and storybook.info.yml configuration is like this:

components: namespaces: atoms: - src/components/01-atoms molecules: - src/components/02-molecules organisms: - src/components/03-organisms layouts: - src/components/04-layouts pages: - src/components/05-pages templates: - src/templates

Fig. 21: Drupal namespaces for nesting components.

storybook.libraries.yml

The recommended method for adding CSS and JS to components or a theme in Drupal is by using Drupal libraries. In our project we would create a library for each component in which we will include any CSS or JS the component needs. In addition, we need to create a global library which includes all the global and utilities styles. Here are examples of libraries we can add in storybook.libraries.yml.

global: version: VERSION css: base: dist/css/reset.css: {} dist/css/base.css: {} dist/css/utilities.css: {} button: css: component: dist/css/button.css: {} card: css: component: dist/css/card.css: {} title: css: component: dist/css/title.css: {}

Fig. 22: Drupal libraries for global styles and component's styles.

/templates

Drupal's templates' directory can be created anywhere within the theme. I typically like to create it inside the src directory. Go ahead and create it now.

  • Inside storybook.info.yml, add a new Twig namespace for the templates directory. See example above. Update your path accordingly based on where you created your templates directory.

P.S: When the Vite project was originally created at the begining of the post, Vite created files such as App.css, App.js, main.js, and index.html. All these files are in the root of the project and can be deleted. It won't affect any of the work we've done, but Vite will no longer run on its own, which we don't need it to anyway.

In closing

I realize this is a very long post, but there is really no way around it when covering these many topics in a single post. I hope you found the content useful and can apply it to your next Drupal project. There are different ways to do what I've covered in this post, and I challenge you to find better and more efficient ways. For now, thanks for visiting.

Download the theme

A full version of the Drupal theme built with this post can be downloaded.

Download the theme

Make sure you are using the theme branch from the repo.

Categories: FLOSS Project Planets

Dirk Eddelbuettel: RApiSerialize 0.1.4 on CRAN: Added C++ Namespace

Planet Debian - Sat, 2024-09-28 20:58

A new minor release 0.1.5 of RApiSerialize arrived on CRAN today. The RApiSerialize package is used by both my RcppRedis as well as by Travers excellent qs package. This release adds an optional C++ namespace, available when the API header file is included in a C++ source file. And as one often does, the release also brings a few small updates to different aspects of the packaging.

Changes in version 0.1.4 (2024-09-28)
  • Add C++ namespace in API header (Dirk in #9 closing #8)

  • Several packaging updates: switched to Authors@R, README.md badge updates, added .editorconfig and cleanup

Courtesy of my CRANberries, there is a diffstat report relative to previous release. More details are at the RApiSerialize page; code, issue tickets etc at the GitHub repositoryrapiserializerepo.

If you like this or other open-source work I do, you can sponsor me at GitHub.

This post by Dirk Eddelbuettel originated on his Thinking inside the box blog. Please report excessive re-aggregation in third-party for-profit settings.

Categories: FLOSS Project Planets

Pages