FLOSS Project Planets
Sven Hoexter: GKE version 1.31.1-gke.1678000+ is a baddy
Just a "warn your brothers" for people foolish enough to use GKE and run on the Rapid release channel.
Update from version 1.31.1-gke.1146000 to 1.31.1-gke.1678000 is causing trouble whenever NetworkPolicy resources and a readinessProbe are configured. As a workaround we started to remove the NetworkPolicy resources. E.g. when kustomize is involved with a patch like this:
- patch: |- $patch: delete apiVersion: "networking.k8s.io/v1" kind: NetworkPolicy metadata: name: dummy target: kind: NetworkPolicyWe tried to update to the latest version - right now 1.31.1-gke.2008000 - which did not change anything. Behaviour is pretty much erratic, sometimes it still works and sometimes the traffic is denied. It also seems that there is some relevant fix in 1.31.1-gke.1678000 because that is now the oldest release of 1.31.1 which I can find in the regular and rapid release channels. The last known good version 1.31.1-gke.1146000 is not available to try a downgrade.
Trey Hunner: Adding keyboard shortcuts to the Python REPL
I talked about the new Python 3.13 REPL a few months ago and after 3.13 was released. I think it’s awesome.
I’d like to share a secret feature within the Python 3.13 REPL which I’ve been finding useful recently: adding custom keyboard shortcuts.
This feature involves a PYTHONSTARTUP file, use of an unsupported Python module, and dynamically evaluating code.
In short, we may be getting ourselves into trouble. But the result is very neat!
Thanks to Łukasz Llanga for inspiring this post via his excellent EuroPython keynote talk.
The goal: keyboard shortcuts in the REPLFirst, I’d like to explain the end result.
Let’s say I’m in the Python REPL on my machine and I’ve typed numbers =:
1 >>> numbers =I can now hit Ctrl-N to enter a list of numbers I often use while teaching (Lucas numbers):
1 numbers = [2, 1, 3, 4, 7, 11, 18, 29]That saved me some typing!
Getting a prototype workingFirst, let’s try out an example command.
Copy-paste this into your Python 3.13 REPL:
1 2 3 4 5 6 7 8 9 10 11 from _pyrepl.simple_interact import _get_reader from _pyrepl.commands import Command class Lucas(Command): def do(self): self.reader.insert("[2, 1, 3, 4, 7, 11, 18, 29]") reader = _get_reader() reader.commands["lucas"] = Lucas reader.bind(r"\C-n", "lucas")Now hit Ctrl-N.
If all worked as planned, you should see that list of numbers entered into the REPL.
Cool! Now let’s generalize this trick and make Python run our code whenever it starts.
But first… a disclaimer.
Here be dragons 🐉Notice that _ prefix in the _pyrepl module that we’re importing from? That means this module is officially unsupported.
The _pyrepl module is an implementation detail and its implementation may change at any time in future Python versions.
In other words: _pyrepl is designed to be used by Python’s standard library modules and not anyone else. That means that we should assume this code will break in a future Python version.
Will that stop us from playing with this module for the fun of it?
It won’t.
Creating a PYTHONSTARTUP fileSo we’ve made one custom key combination for ourselves. How can we setup this command automatically whenever the Python REPL starts?
We need a PYTHONSTARTUP file.
When Python launches, if it sees a PYTHONSTARTUP environment variable it will treat that environment variable as a Python file to run on startup.
I’ve made a /home/trey/.python_startup.py file and I’ve set this environment variable in my shell’s configuration file (~/.zshrc):
1 export PYTHONSTARTUP=$HOME/.python_startup.pyTo start, we could put our single custom command in this file:
1 2 3 4 5 6 7 8 9 10 11 12 13 try: from _pyrepl.simple_interact import _get_reader from _pyrepl.commands import Command except ImportError: pass # Not in the new pyrepl OR _pyrepl implementation changed else: class Lucas(Command): def do(self): self.reader.insert("[2, 1, 3, 4, 7, 11, 18, 29]") reader = _get_reader() reader.commands["lucas"] = Lucas reader.bind(r"\C-n", "lucas")Note that I’ve stuck our code in a try-except block. Our code only runs if those _pyrepl imports succeed.
Note that this might still raise an exception when Python starts if the reader object’s command attribute or bind method change in a way that breaks our code.
Personally, I’d like to see those breaking changes occur print out a traceback the next time I upgrade Python. So I’m going to leave those last few lines without their own catch-all exception handler.
Generalizing the codeHere’s a PYTHONSTARTUP file with a more generalized solution:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 try: from _pyrepl.simple_interact import _get_reader from _pyrepl.commands import Command except ImportError: pass else: # Hack the new Python 3.13 REPL! cmds = { r"\C-n": "[2, 1, 3, 4, 7, 11, 18, 29]", r"\C-f": '["apples", "oranges", "bananas", "strawberries", "pears"]', } from textwrap import dedent reader = _get_reader() for n, (key, text) in enumerate(cmds.items(), start=1): name = f"CustomCommand{n}" exec(dedent(f""" class _cmds: class {name}(Command): def do(self): self.reader.insert({text!r}) reader.commands[{name!r}] = {name} reader.bind({key!r}, {name!r}) """)) # Clean up all the new variables del _get_reader, Command, dedent, reader, cmds, text, key, name, _cmds, nThis version uses a dictionary to map keyboard shortcuts to the text they should insert.
Note that we’re repeatedly building up a string of Command subclasses for each shortcut, using exec to execute the code for that custom Command subclass, and then binding the keyboard shortcut to that new command class.
At the end we then delete all the variables we’ve made so our REPL will start the clean global environment we normally expect it to have:
1 2 3 4 Python 3.13.0 (main, Oct 8 2024, 10:37:56) [GCC 11.4.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>> dir() ['__annotations__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__']Is this messy?
Yes.
Is that a needless use of a dictionary that could have been a list of 2-item tuples instead?
Yes.
Does this work?
Yes.
Doing more interesting and risky stuffNote that there are many keyboard shortcuts that may cause weird behaviors if you bind them.
For example, if you bind Ctrl-i, your binding may trigger every time you try to indent. And if you try to bind Ctrl-m, your binding may be ignored because this is equivalent to hitting the Enter key.
So be sure to test your REPL carefully after each new binding you try to invent.
If you want to do something more interesting, you could poke around in the _pyrepl package to see what existing code you can use/abuse.
For example, here’s a very hacky way of making a binding to Ctrl-x followed by Ctrl-r to make this import subprocess, type in a subprocess.run line, and move your cursor between the empty string within the run call:
1 2 3 4 5 6 7 8 9 10 11 12 class _cmds: class Run(Command): def do(self): from _pyrepl.commands import backward_kill_word, left backward_kill_word(self.reader, self.event_name, self.event).do() self.reader.insert("import subprocess\n") code = 'subprocess.run("", shell=True)' self.reader.insert(code) for _ in range(len(code) - code.index('""') - 1): left(self.reader, self.event_name, self.event).do() reader.commands["subprocess_run"] = _cmds.Run reader.bind(r"\C-x\C-r", "subprocess_run") What keyboard shortcuts are available?As you play with customizing keyboard shortcuts, you’ll likely notice that many key combinations result in strange and undesirable behavior when overridden.
For example, overriding Ctrl-J will also override the Enter key… at least it does in my terminal.
I’ll list the key combinations that seem unproblematic on my setup with Gnome Terminal in Ubuntu Linux.
Here are Control key shortcuts that seem to be complete unused in the Python REPL:
- Ctrl-N
- Ctrl-O
- Ctrl-P
- Ctrl-Q
- Ctrl-S
- Ctrl-V
Note that overriding Ctrl-H is often an alternative to the backspace key
Here are Alt/Meta key shortcuts that appear unused on my machine:
- Alt-A
- Alt-E
- Alt-G
- Alt-H
- Alt-I
- Alt-J
- Alt-K
- Alt-M
- Alt-N
- Alt-O
- Alt-P
- Alt-Q
- Alt-S
- Alt-V
- Alt-W
- Alt-X
- Alt-Z
You can add an Alt shortcut by using \M (for “meta”). So r"\M-a" would capture Alt-A just as r"\C-a" would capture Ctrl-A.
Here are keyboard shortcuts that can be customized but you might want to consider whether the current default behavior is worth losing:
- Alt-B: backward word (same as Ctrl-Left)
- Alt-C: capitalize word (does nothing on my machine…)
- Alt-D: kill word (delete to end of word)
- Alt-F: forward word (same as Ctrl-Right)
- Alt-L: downcase word (does nothing on my machine…)
- Alt-U: upcase word (does nothing on my machine…)
- Alt-Y: yank pop
- Ctrl-A: beginning of line (like the Home key)
- Ctrl-B: left (like the Left key)
- Ctrl-E: end of line (like the End key)
- Ctrl-F: right (like the Right key)
- Ctrl-G: cancel
- Ctrl-H: backspace (same as the Backspace key)
- Ctrl-K: kill line (delete to end of line)
- Ctrl-T: transpose characters
- Ctrl-U: line discard (delete to beginning of line)
- Ctrl-W: word discard (delete to beginning of word)
- Ctrl-Y: yank
- Alt-R: restore history (within history mode)
Find something fun while playing with the _pyrepl package’s inner-workings?
I’d love to hear about it! Comment below to share what you found.
Real Python: Beautiful Soup: Build a Web Scraper With Python
Web scraping is the automated process of extracting data from the internet. The Python libraries Requests and Beautiful Soup are powerful tools for the job. To effectively harvest the vast amount of data available online for your research, projects, or personal interests, you’ll need to become skilled at web scraping.
In this tutorial, you’ll learn how to:
- Inspect the HTML structure of your target site with your browser’s developer tools
- Decipher data encoded in URLs
- Use Requests and Beautiful Soup for scraping and parsing data from the internet
- Step through a web scraping pipeline from start to finish
- Build a script that fetches job offers from websites and displays relevant information in your console
If you like learning with hands-on examples and have a basic understanding of Python and HTML, then this tutorial is for you! Working through this project will give you the knowledge and tools you need to scrape any static website out there on the World Wide Web. You can download the project source code by clicking on the link below:
Get Your Code: Click here to download the free sample code that you’ll use to learn about web scraping in Python.
Take the Quiz: Test your knowledge with our interactive “Beautiful Soup: Build a Web Scraper With Python” quiz. You’ll receive a score upon completion to help you track your learning progress:
Interactive Quiz
Beautiful Soup: Build a Web Scraper With PythonIn this quiz, you'll test your understanding of web scraping using Python. By working through this quiz, you'll revisit how to inspect the HTML structure of a target site, decipher data encoded in URLs, and use Requests and Beautiful Soup for scraping and parsing data from the Web.
What Is Web Scraping?Web scraping is the process of gathering information from the internet. Even copying and pasting the lyrics of your favorite song can be considered a form of web scraping! However, the term “web scraping” usually refers to a process that involves automation. While some websites don’t like it when automatic scrapers gather their data, which can lead to legal issues, others don’t mind it.
If you’re scraping a page respectfully for educational purposes, then you’re unlikely to have any problems. Still, it’s a good idea to do some research on your own to make sure you’re not violating any Terms of Service before you start a large-scale web scraping project.
Reasons for Automated Web ScrapingSay that you like to surf—both in the ocean and online—and you’re looking for employment. It’s clear that you’re not interested in just any job. With a surfer’s mindset, you’re waiting for the perfect opportunity to roll your way!
You know about a job site that offers precisely the kinds of jobs you want. Unfortunately, a new position only pops up once in a blue moon, and the site doesn’t provide an email notification service. You consider checking up on it every day, but that doesn’t sound like the most fun and productive way to spend your time. You’d rather be outside surfing real-life waves!
Thankfully, Python offers a way to apply your surfer’s mindset. Instead of having to check the job site every day, you can use Python to help automate the repetitive parts of your job search. With automated web scraping, you can write the code once, and it’ll get the information that you need many times and from many pages.
Note: In contrast, when you try to get information manually, you might spend a lot of time clicking, scrolling, and searching, especially if you need large amounts of data from websites that are regularly updated with new content. Manual web scraping can take a lot of time and be highly repetitive and error-prone.
There’s so much information on the internet, with new information constantly being added. You’ll probably be interested in some of that data, and much of it is out there for the taking. Whether you’re actually on the job hunt or just want to automatically download all the lyrics of your favorite artist, automated web scraping can help you accomplish your goals.
Challenges of Web ScrapingThe internet has grown organically out of many sources. It combines many different technologies, styles, and personalities, and it continues to grow every day. In other words, the internet is a hot mess! Because of this, you’ll run into some challenges when scraping the web:
-
Variety: Every website is different. While you’ll encounter general structures that repeat themselves, each website is unique and will need personal treatment if you want to extract the relevant information.
-
Durability: Websites constantly change. Say you’ve built a shiny new web scraper that automatically cherry-picks what you want from your resource of interest. The first time you run your script, it works flawlessly. But when you run the same script a while later, you run into a discouraging and lengthy stack of tracebacks!
Unstable scripts are a realistic scenario because many websites are in active development. If a site’s structure changes, then your scraper might not be able to navigate the sitemap correctly or find the relevant information. The good news is that changes to websites are often small and incremental, so you’ll likely be able to update your scraper with minimal adjustments.
Still, keep in mind that the internet is dynamic and keeps on changing. Therefore, the scrapers you build will probably require maintenance. You can set up continuous integration to run scraping tests periodically to ensure that your main script doesn’t break without your knowledge.
An Alternative to Web Scraping: APIsSome website providers offer application programming interfaces (APIs) that allow you to access their data in a predefined manner. With APIs, you can avoid parsing HTML. Instead, you can access the data directly using formats like JSON and XML. HTML is primarily a way to visually present content to users.
When you use an API, the data collection process is generally more stable than it is through web scraping. That’s because developers create APIs to be consumed by programs rather than by human eyes.
The front-end presentation of a site might change often, but a change in the website’s design doesn’t affect its API structure. The structure of an API is usually more permanent, which means it’s a more reliable source of the site’s data.
However, APIs can change as well. The challenges of both variety and durability apply to APIs just as they do to websites. Additionally, it’s much harder to inspect the structure of an API by yourself if the provided documentation lacks quality.
Read the full article at https://realpython.com/beautiful-soup-web-scraper-python/ »[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short & sweet Python Trick delivered to your inbox every couple of days. >> Click here to learn more and see examples ]
Drupal life hack's: Secrets of Secure Development in Drupal: Key Functions
Real Python: Quiz: Beautiful Soup: Build a Web Scraper With Python
In this quiz, you’ll test your understanding of web scraping with Python, Requests, and Beautiful Soup.
By working through this quiz, you’ll revisit how to inspect the HTML structure of your target site with your browser’s developer tools, decipher data encoded in URLs, use Requests and Beautiful Soup for scraping and parsing data from the Web, and gain an understanding of what a web scraping pipeline looks like.
[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short & sweet Python Trick delivered to your inbox every couple of days. >> Click here to learn more and see examples ]
Golems GABB: Using JavaScript Frameworks - React, Vue, Angular in Drupal
The integration of JavaScript frameworks, like React, Vue, and Angular, with Drupal has sparked a wave of creativity and innovation. It goes beyond building websites. This blog explores the benefits and methods of integrating these frameworks with Drupal, demonstrating how this fusion enhances front-end development and user engagement.
Traditional static websites and strict CMS constraints are becoming a thing of the past. Nowadays, developers are embracing the adaptability and engagement provided by JavaScript frameworks to design UI within the Drupal environment.
To really understand how JavaScript frameworks such as React, Vue, and Angular work with Drupal, you need to know about the frontend environment of Drupal and the difficulties developers meet while creating complicated user interfaces in this strong content management system.
Thomas Lange: 30.000 FAIme jobs created in 7 years
The number of FAIme jobs has reached 30.000. Yeah!
At the end of this November the FAIme web service for building customized ISOs turns 7 years old.
It had reached 10.000 jobs in March 2021 and 20.000 jobs were reached in
June 2023. A nice increase of the usage.
Here are some statistics for the jobs processed in 2024:
Type of jobs 3% cloud image 11% live ISO 86% install ISO Distribution 2% bullseye 8% trixie 12% ubuntu 24.04 78% bookworm Misc- 18% used a custom postinst script
- 11% provided their ssh pub key for passwordless root login
- 50% of the jobs didn't included a desktop environment at all, the others used GNOME, XFCE or KDE or the Ubuntu desktop the most.
- The biggest ISO was a FAIme job which created a live ISO with a desktop and some additional packages This job took 30min to finish and the resulting ISO was 18G in size.
The cloud and live ISOs need more time for their creation because the FAIme server needs to unpack and install all packages. For the install ISO the packages are only downloaded. The amount of software packages also affects the build time. Every ISO is build in a VM on an old 6-core E5-1650 v2. Times given are calculated from the jobs of the past two weeks.
Job type Avg Max install no desktop 1 min 2 min install GNOME 2 min 5 minThe times for Ubuntu without and with desktop are one minute higher than those mentioned above.
Job type Avg Max live no desktop 4 min 6 min live GNOME 8 min 11 minThe times for cloud images are similar to live images.
A New FeatureFor a few weeks now, the system has been showing the number of jobs ahead of you in the queue when you submit a job that cannot be processed immediately.
The Next MilestoneAt the end of this years the FAI project will be 25 years old. If you have a success story of your FAI usage to share please post it to the linux-fai mailing list or send it to me. Do you know the FAI questionnaire ? A lot of reports are already available.
Here's an overview what happened in the past 20 years in the FAI project.
About FAImeFAIme is the service for building your own customized ISO via a web interface. You can create an installation or live ISO or a cloud image. Several Debian releases can be selected and also Ubuntu server or Ubuntu desktop installation ISOs can be customized. Multiple options are available like selecting a desktop and the language, adding your own package list, choosing a partition layout, adding a user, choosing a backports kernel, adding a postinst script and some more.
Python Bytes: #407 Back to the future, destination 3.14
Zato Blog: Salesforce API integrations and connected apps
This instalment in a series of articles about API integrations with Salesforce covers connected apps - how to create them and how to obtain their credentials needed to exchange REST messages with Salesforce.
In Salesforce's terminology, a connected app is, essentially, an API client. It has credentials, a set of permissions, and it works on behalf of a user in an automated manner.
In particular, the kind of a connected app that I am going to create below is one that can be used in backend, server-side integrations that operate without any direct input from end users or administrators, i.e. the app is created once, its permissions and credentials are set once, and then it is able to work uninterrupted in the background, on server side.
Server-side systems are quite unlike other kinds of apps, such as mobile ones, that assume there is a human operator involved - they have their own work characteristics, related yet different, and I am not going to cover them here.
Note that permission types and their scopes are a separate, broad subject and they will described in a separate how-to article.
Finally, I assume that you are either an administrator in a Salesforce organization or that you are preparing information for another person with similar grants in Salesforce.
Conceptually, there is nothing particularly unusual about Salesforce connected apps, it is just its own mini-world of jargon and, at the end of the day, it simply enables you to invoke APIs that Salesforce is built on. It is just that knowing where to click, what to choose and how to navigate the user interface can be a daunting challenge that this article hopes to make easier to overcome.
The stepsFor an automated, server-side connected app to make use of Salesforce APIs, the requirements are:
- Having access to username/password credentials
- Creating a connected app
- Granting permissions to the app (not covered in this article)
- Obtaining a customer key and customer secret for the app
You will note that there are four credentials in total:
- Username
- Password
- Customer key
- Customer secret
Also, depending on what chapter of the Salesforce documentation you are reading, you will note that the customer key can be also known as "client_id" whereas another name for the customer secret is "client_secret". These two pairs mean the same.
Access to username/password credentialsFor starters, you need to have an account in Salesforce, a combination of username + password that you can log in with and on whose behalf the connected app will be created:
Creating a connected appOnce you are logged in, go to Setup in the top right-hand corner:
In the search box, look up "app manager":
Next, click the "New Connected App" button to the right:
Fill out the basic details such as "Connect App Name" and make sure that you select "Enable OAuth Settings". Then, given that in this document we are not dealing with the subject of permissions at all, grant full access to the connected app and finally click "Save" at the bottom of the page.
Obtaining a customer key and customer secretWe have a connected app but we still do not know what its customer key and secret are. To reveal it, go to the "App Manager" once more, either via the search box or using the menu on the left hand side.
Find your app in the list and click "View" in the list of actions. Observe that it is "View", not "Edit" or "Manage", where you can check what the credentials are:
The customer key and secret van be now revealed in the "API (Enable OAuth Settings)" section:
This concludes the process - you have a connected app and all the credentials needed now.
TestingSeeing as this document is part of a series of how-tos in the context of Zato, if you would like to integrate with Salesforce in Python, at this point you will be able to follow the steps in another where everything is detailed separately.
Just as a quick teaser, it would look akin to the below.
... # Salesforce REST API endpoint to invoke 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. response = client.post(path, request) ...On a much lower level, however, if you would just like to quickly test out whether you configured the connected app correctly, you can invoke from command line a Salesforce REST endpoint that will return an OAuth token, as below.
Note that, as I mentioned it previously, client_id is the same as customer key and client_secret is the same as customer secret.
curl https://example.my.salesforce.com/services/oauth2/token \ -H "X-PrettyPrint: 1" \ --header 'Content-Type: application/x-www-form-urlencoded' \ --data-urlencode 'grant_type=password' \ --data-urlencode 'username=hello@example.com' \ --data-urlencode 'password=my.password' \ --data-urlencode 'client_id=my.customer.key' \ --data-urlencode 'client_secret=my.client.secret'The result will be, for instance:
{ "access_token" : "008e0000000PTzLPb!4Vzm91PeIWJo.IbPzoEZf2ygEM.6cavCt0YwAGSM", "instance_url" : "https://example.my.salesforce.com", "id" : "https://login.salesforce.com/id/008e0000000PTzLPb/0081fSUkuxPDrir000j1", "token_type" : "Bearer", "issued_at" : "1649064143961", "signature" : "dwb6rwNIzl76kZq8lQswsTyjW2uwvTnh=" }Above, we have an OAuth bearer token on output - this can be used in subsequent, business REST calls to Salesforce but how to do it exactly in practice is left for another article.
Next steps:➤ Read about how to use Python to build and integrate enterprise APIs that your tests will cover
➤ Python API integration tutorial
➤ Python Integration platform as a Service (iPaaS)
➤ What is an Enterprise Service Bus (ESB)? What is SOA?
qtatech.com blog: La fin de Drupal 7 : Pourquoi tant de sites choisissent WordPress ?
Since January 5, 2025, Drupal 7 has officially reached its end of life. This iconic Content Management System (CMS), used by thousands of sites worldwide, no longer receives security updates or official support. This deadline has prompted many site administrators to rethink their strategy and select a new platform to ensure continuity.
Droptica: Data Migration to Drupal Using Products from External Database - Guide
How can you perform a product data migration from an external database to Drupal using the tools available within the Migrate API? In this blog post, I’ll show you how to connect to the database, prepare the data structure, and use the migration tools available in Drush. This entry is aimed at people who have already had experience with migrations as well as those who are just getting started with them. I encourage you to read the article or watch the video of the “Nowoczesny Drupal” series.
PreviousNext: New resource: How to prepare open source Requests for Proposals
The Drupal Association has published client guides to RFPs that prioritise open source software solutions.
by fiona.crowson / 28 October 2024In a recent blog post, 'How to write an RFP for Open Source Solutions: Featuring Drupal Certified Partners', the Drupal Association outlines:
- the advantages of open source software
- tips for finding the ideal service provider (and why Drupal Certified Partners like PreviousNext make for good partners)
- guidance for crafting a successful RFP
- strategies for evaluating proposals
Clients also have access to a downloadable open source Request For Proposal (aka Request For Quote) template.
The core of the guide provides a detailed overview about why choosing a Drupal Certified Partner is the key to the technical expertise, smooth collaboration and commitment to quality and innovation that helps ensure the success of your projects. PreviousNext has been able to attain the current top ranked Drupal Certified Partner status globally by demonstrating our proven track record, commitment to the Drupal open source community and our verifiable capabilities.
Our team is highly experienced and happy to answer your questions about the advantages of Drupal, so please feel free to get in touch.
Quick links- How to write an RFP article
- RFP template download
Kwave Update - October 2024
Kwave is an audio editor based on the KDE Frameworks. It was started in 1998 by Martin Wilz, and Thomas Eschenbacher has been the main developer since 1999. In recent years development has slowed. I wanted to do some software development and contribute to KDE, and I’m interested in audio, so towards the end of 2023 I started working on Kwave.
Kwave had not been ported to Qt 6 and KDE Frameworks 6 yet, so that’s what I started working towards. My first merge requests were to update deprecated code. (MR Convert plugin desktop files to json, MR Port away from deprecated Qt API, MR port away from deprecated I18N_NOOP macros, MR bump KF5_MIN_VERSION and update where KMessageBox API has been deprecated, MR port QRegExp to QRegularExpression)
With that preparatory work done, I worked at porting Kwave to Qt 6 and KDE Frameworks 6. Most of that work was straight-forward. The biggest changes were in Qt Multimedia, which Kwave can use for playback and recording. I finally got that done and merged in August 2024, just after version 24.08 was branched, so that change will get released in version 24.12 in December 2024. (MR port to Qt6 and KF6)
Next I did some code cleanup. (MR use ECMGenerateExportHeader, MR add braces to avoid ambiguous else, MR call KCrash::initialize() after KAboutData::setApplicationData())
Laurent Montel added the FreeBSD job to the Continuous Integration configuration, but the build failed initially. I’ve never ran FreeBSD, but with a few tries and pushing changes to trigger CI, I managed to get the CI to pass. I’m glad Laurent took the initiative here, because the FreeBSD job uses clang, so with the existing Linux job using gcc, CI makes sure Kwave builds with both compilers now. (MR Add freebsd)
I applied for a KDE Developer account and got approved on August 24, 2024. Now I could commit changes myself instead of having to remind others to do it.
Carl Schwan cleaned up some code and updated the zoom toolbar to use standard icons, which enabled removing the built-in zoom icons. (MR Modernize ZoomToolbar) That was the incentive I needed to remove the rest of the built-in icons and use standard icons instead, which helps Kwave fit the users theme better. (MR use icons from current theme) I also reordered the playback toolbar in a way that seemed more logical to me. (MR update player toolbar)
I investigated a bug: Kwave Playback settings dialog loads incorrectly until you switch playback methods and fixed it in MR: make sure a valid method gets selected when PlayBackDialog opens
I have some more work in progress, and I plan to continue working on Kwave. I will try to blog about what I’m doing, but I’m not going to commit to any regular schedule.
Get InvolvedKwave depends on the rest of KDE. It is built on the Frameworks, and the KDE sysadmin team keeps the infrastructure running. You can help KDE by getting involved, or at least donate.
If you would like to help improve Kwave, use it and try out its features! If you have questions or ideas, discuss them. If you find bugs, report them. If you want to get involved with development, download the source code and start hacking!
If you think my own work on Kwave is worth something and you can afford it, you can donate to me through Liberapay, Stripe, or PayPal.
Dries Buytaert: Acquia Engage NYC 2024 product showcase
At Acquia Engage NYC this week, our partner and customer conference, we shared how Acquia's Digital Experience Platform (DXP) helps organizations deliver digital experiences through three key capabilities:
- Content: Create, manage and deliver digital content and experiences - from images and videos to blog posts, articles, and landing pages - consistently across all your digital channels.
- Optimize: Continuously improve your digital content and experiences by improving accessibility, readability, brand compliance, and search engine optimization (SEO).
- Insights: Understand how people interact with your digital experiences, segment audiences based on their behavior and interests, and deliver personalized content that drives better engagement and conversion rates.
Since our last Acquia Engage conference in May, roughly six months ago, we've made some great progress, and we announced some major innovations and updates across our platform.
The Acquia Open DXP platform consists of three pillars - Content, Optimize, and Insight - with specialized products in each category to help organizations create, improve, and personalize digital experiences. Simplify video creation in Acquia DAMVideo is one of the most engaging forms of media, but it's also one of the most time-consuming and expensive to create. Producing professional, branded videos has traditionally required significant time, budget, and specialized skills. Our new Video Creator for DAM changes this equation. By combining templating, AI, and DAM's workflow functionality, organizations can now create professional, on-brand videos in minutes rather than days.
Make assets easier to find in Acquia DAMManaging large digital asset libraries can become increasingly overwhelming. Traditional search methods rely on extensive metadata tagging and manual filtering options. Depending on what you are looking for, it might be difficult to quickly find the right assets.
To address this, we introduced Acquia DAM Copilot, which transforms the experience through conversational AI. Instead of navigating complicated filter menus, users can now simply type natural requests like "show me photos of bikes outside" and refine their search conversationally with commands like "only show bikes from the side view". This AI-powered approach eliminates the need for extensive tagging and makes finding the right content intuitive and fast.
Easier site building with DrupalI updated the Acquia Engage audience on Drupal CMS (also known as Drupal Starshot), a major initiative I'm leading in the Drupal community with significant support from Acquia. I demonstrated several exciting innovations coming to Drupal: "recipes" to simplify site building, AI-powered site creation capabilities, and a new Experience Builder that will transform how we build Drupal websites.
Many in the audience had already watched my DrupalCon Barcelona keynote and expressed continued enthusiasm for the direction of Drupal CMS and our accelerated pace of innovation. Even after demoing it multiple times the past month, I'm still very excited about it myself. If you want to learn more, be sure to check out my DrupalCon presentation!
Improving content ranking with Acquia SEOCreating content that ranks well in search engines traditionally requires both specialized SEO expertise and skilled content writers - making it an expensive and time-consuming process. Our new SEO Copilot, powered by Conductor, integrated directly into Drupal's editing experience, provides real-time guidance on keyword optimization, content suggestions, length recommendations, and writing complexity for your target audience. This helps content teams create search-engine-friendly content more efficiently, without needing deep SEO expertise.
Improving content quality with Acquia OptimizeWe announced the rebranding of Monsido to Acquia Optimize and talked about two major improvements to this offering.
First, we improved how organizations create advanced content policies. Creating advanced content policies usually requires some technical expertise, as it can involve writing regular expressions. Now, users can simply describe in plain language what they want to monitor. For example, they could enter something like "find language that might be insensitive to people with disabilities", and AI will help create the appropriate policy rules. Acquia Optimize will then scan content across all your websites to detect any violations of those rules.
Second, we dramatically shortened the feedback loop for content checking. Previously, content creators had to publish their content and then wait for scheduled scans to discover problems with accessibility, policy compliance or technical SEO - a process that could take a couple of days. Now, they can get instant feedback. Authors can request a check while they work, and the system immediately flags accessibility issues, content policy violations, and other problems, allowing them to fix problems while the content is being written. This shift from "publish and wait" to "check and fix" helps teams maintain higher content quality standards, allows them to work faster, and can prevent non-compliant content from ever going live.
FedRAMP for Acquia Cloud NextWe were excited to announce that our next-generation Drupal Cloud, Acquia Cloud Next (ACN), has achieved FedRAMP accreditation, just like our previous platform, which remains FedRAMP accredited.
This means our government customers can now migrate their Drupal sites onto our latest cloud platform, taking advantage of improved autoscaling, self-healing, and cutting-edge features. We already have 56 FedRAMP customers hosting their Drupal sites on ACN, including Fannie Mae, The US Agency for International Development, and the Department of Education, to name a few.
Improved fleet management for DrupalAcquia Cloud Site Factory is a platform that helps organizations manage fleets of Drupal sites from a single dashboard, making it easier to launch, update, and scale sites. Over the past two years, we've been rebuilding Site Factory on top of Acquia Cloud Next, integrating them more closely. Recently, we reached a major milestone in this journey. At Engage, we showcased Multi-Experience Operations (MEO) to manage multiple Drupal codebases across your portfolio of sites.
Previously, all sites in a Site Factory instance had to run the same Drupal code, requiring simultaneous updates across all sites. Now, organizations can run sites on different codebases and update them independently. This added flexibility is invaluable for large organizations managing hundreds or thousands of Drupal sites, allowing them to update at their own pace and maintain different Drupal versions where needed.
Improved conversion rates with Acquia ConvertUnderstanding user behavior is key to optimizing digital experiences, but interpreting the data and deciding on next steps can be challenging. We introduced some new Acquia Convert features (powered by VWO) to solve this.
First, advanced heat-mapping shows exactly how users interact with your pages, where they click first, how far they scroll, and where they show signs of frustration (like rage clicks).
Next, and even more powerful, is our new Acquia Convert Copilot that automatically analyzes this behavioral data to suggest specific improvements. For example, if the AI notices high interaction with a pricing slider but also signs of user confusion, it might suggest an A/B test to clarify the slider's purpose. This helps marketers and site builders make data-driven decisions and improve conversion rates.
Privacy-first analytics with Piwik ProAs data privacy regulations become stricter globally, organizations face growing challenges with web analytics. Google Analytics has been banned in several European countries for not meeting data sovereignty requirements, leaving organizations scrambling for compliant alternatives.
We announced a partnership with Piwik Pro to address this need. Piwik Pro offers a privacy-first analytics solution that maintains compliance with global data regulations by allowing organizations to choose where their data is stored and maintaining full control over their data.
This makes it an ideal solution for organizations that operate in regions with strict data privacy laws, or any organization that wants to ensure their analytics solution remains compliant with evolving privacy regulations.
After the Piwik Pro announcement at Acquia Engage, I spoke with several customers who are already using Piwik Pro. Most worked in healthcare and other sectors handling sensitive data. They were excited about our partnership and a future that brings deeper integration between Piwik Pro, Acquia Optimize, Drupal, and other parts of our portfolio.
ConclusionThe enthusiasm from our customers and partners at Acquia Engage always reinvigorates me. None of these innovations would be possible without the dedication of our teams at Acquia. I'm grateful for their hard work in bringing these innovations to life, and I'm excited for what is next!
#! code: Drupal 11: Batch Operations Built Into Drupal
This is the sixth 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, using the finished state to control batch processing, processing CSV files through a batch process and finally adding to running batch processes. These articles give a good grounding of how to use the Drupal Batch API.
In this article we will look at how the Batch API is used within Drupal. The Batch API in Drupal is either used to perform a task, which I will call "direct", or to pass on the batch operations to a hook, which I will call "indirect". These aren't official terms you understand, I'm just using them here to separate how Drupal uses the Batch API. I find these terms useful to describe where the batch is running.
Let's look at direct usage first.
DirectDirect usage just means that a method in Drupal creates a BatchBuilder object and then uses that object to setup and trigger the batch run (via the batch_set() function). This is used in a variety of situations all over Drupal, including:
philipnorton42 Sun, 10/27/2024 - 18:23Linux App Summit 2024
As we have been doing yearly, a few weeks ago we had the 2024 edition of Linux App Summit (LAS). For those of you who don’t know, the Linux App Summit is a conference co-organised between KDE and GNOME among others where to bring together the different stakeholders of the linux ecosystem to make sure we have all the collaboration tools in place to have a great state of the art platform for the uses the world needs from us.
This year it was special in that since it became the Linux App Summit, we held it outside of Europe! We had LAS in Monterrey, the northernmost part of México in the ITESM (Instituto Tecnológico y de Estudios Superiores de Monterrey), a really nice campus and a beautiful venue.
Besides meeting people from other projects as I’d normally do in LAS, this year I had the added opportunity to meet the community the other side of the ocean. There certainly are good differences between how we organise FOSS communities Europe and there, it’s always useful to experience and iterate to ensure we are truly creating a community for everyone.
LAS ’25, Call for hostsAre you considering bringing such communities to your home town? Please reach out, you can find some information how to do that here: https://linuxappsummit.org/bids/.
In my opinion, organising a conference is one of the best ways to bring FOSS talent to where you are. It’s often hard to find new ways to be part of what we do, this is a great one. I personally had the opportunity to do it in LAS’19 in Barcelona and it was a great experience.
LAS has the added value of being a melting pot of people from different communities so it’s a great opportunity to meet people that you might not crossed paths with before!
Enrico Zini: Typing decorators for class members with optional arguments
This looks straightforward and is far from it. I expect tool support will improve in the future. Meanwhile, this blog post serves as a step by step explanation for what is going on in code that I'm about to push to my team.
Let's take this relatively straightforward python code. It has a function printing an int, and a decorator that makes it argument optional, taking it from a global default if missing:
from unittest import mock default = 42 def with_default(f): def wrapped(self, value=None): if value is None: value = default return f(self, value) return wrapped class Fiddle: @with_default def print(self, value): print("Answer:", value) fiddle = Fiddle() fiddle.print(12) fiddle.print() def mocked(self, value=None): print("Mocked answer:", value) with mock.patch.object(Fiddle, "print", autospec=True, side_effect=mocked): fiddle.print(12) fiddle.print()It works nicely as expected:
$ python3 test0.py Answer: 12 Answer: 42 Mocked answer: 12 Mocked answer: NoneIt lacks functools.wraps and typing, though. Let's add them.
Adding functools.wrapsAdding a simple @functools.wraps, mock unexpectedly stops working:
# python3 test1.py Answer: 12 Answer: 42 Mocked answer: 12 Traceback (most recent call last): File "/home/enrico/lavori/freexian/tt/test1.py", line 42, in <module> fiddle.print() File "<string>", line 2, in print File "/usr/lib/python3.11/unittest/mock.py", line 186, in checksig sig.bind(*args, **kwargs) File "/usr/lib/python3.11/inspect.py", line 3211, in bind return self._bind(args, kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3.11/inspect.py", line 3126, in _bind raise TypeError(msg) from None TypeError: missing a required argument: 'value'This is the new code, with explanations and a fix:
# Introduce functools import functools from unittest import mock default = 42 def with_default(f): @functools.wraps(f) def wrapped(self, value=None): if value is None: value = default return f(self, value) # Fix: # del wrapped.__wrapped__ return wrapped class Fiddle: @with_default def print(self, value): assert value is not None print("Answer:", value) fiddle = Fiddle() fiddle.print(12) fiddle.print() def mocked(self, value=None): print("Mocked answer:", value) with mock.patch.object(Fiddle, "print", autospec=True, side_effect=mocked): fiddle.print(12) # mock's autospec uses inspect.getsignature, which follows __wrapped__ set # by functools.wraps, which points to a wrong signature: the idea that # value is optional is now lost fiddle.print() Adding typingFor simplicity, from now on let's change Fiddle.print to match its wrapped signature:
# Give up with making value not optional, to simplify things :( def print(self, value: int | None = None) -> None: assert value is not None print("Answer:", value) Typing with ParamSpec # Introduce typing, try with ParamSpec import functools from typing import TYPE_CHECKING, ParamSpec, Callable from unittest import mock default = 42 P = ParamSpec("P") def with_default(f: Callable[P, None]) -> Callable[P, None]: # Using ParamSpec we forward arguments, but we cannot use them! @functools.wraps(f) def wrapped(self, value: int | None = None) -> None: if value is None: value = default return f(self, value) return wrapped class Fiddle: @with_default def print(self, value: int | None = None) -> None: assert value is not None print("Answer:", value)mypy complains inside the wrapper, because while we forward arguments we don't constrain them, so we can't be sure there is a value in there:
test2.py:17: error: Argument 2 has incompatible type "int"; expected "P.args" [arg-type] test2.py:19: error: Incompatible return value type (got "_Wrapped[P, None, [Any, int | None], None]", expected "Callable[P, None]") [return-value] test2.py:19: note: "_Wrapped[P, None, [Any, int | None], None].__call__" has type "Callable[[Arg(Any, 'self'), DefaultArg(int | None, 'value')], None]" Typing with CallableWe can use explicit Callable argument lists:
# Introduce typing, try with Callable import functools from typing import TYPE_CHECKING, Callable, TypeVar from unittest import mock default = 42 A = TypeVar("A") # Callable cannot represent the fact that the argument is optional, so now mypy # complains if we try to omit it def with_default(f: Callable[[A, int | None], None]) -> Callable[[A, int | None], None]: @functools.wraps(f) def wrapped(self: A, value: int | None = None) -> None: if value is None: value = default return f(self, value) return wrapped class Fiddle: @with_default def print(self, value: int | None = None) -> None: assert value is not None print("Answer:", value) if TYPE_CHECKING: reveal_type(Fiddle.print) fiddle = Fiddle() fiddle.print(12) # !! Too few arguments for "print" of "Fiddle" [call-arg] fiddle.print() def mocked(self, value=None): print("Mocked answer:", value) with mock.patch.object(Fiddle, "print", autospec=True, side_effect=mocked): fiddle.print(12) fiddle.print()Now mypy complains when we try to omit the optional argument, because Callable cannot represent optional arguments:
test3.py:32: note: Revealed type is "def (test3.Fiddle, Union[builtins.int, None])" test3.py:37: error: Too few arguments for "print" of "Fiddle" [call-arg] test3.py:46: error: Too few arguments for "print" of "Fiddle" [call-arg]typing's documentation says:
Callable cannot express complex signatures such as functions that take a variadic number of arguments, overloaded functions, or functions that have keyword-only parameters. However, these signatures can be expressed by defining a Protocol class with a call() method:
Let's do that!
Typing with Protocol, take 1 # Introduce typing, try with Protocol import functools from typing import TYPE_CHECKING, Protocol, TypeVar, Generic, cast from unittest import mock default = 42 A = TypeVar("A", contravariant=True) class Printer(Protocol, Generic[A]): def __call__(_, self: A, value: int | None = None) -> None: ... def with_default(f: Printer[A]) -> Printer[A]: @functools.wraps(f) def wrapped(self: A, value: int | None = None) -> None: if value is None: value = default return f(self, value) return cast(Printer, wrapped) class Fiddle: # function has a __get__ method to generated bound versions of itself # the Printer protocol does not define it, so mypy is now unable to type # the bound method correctly @with_default def print(self, value: int | None = None) -> None: assert value is not None print("Answer:", value) if TYPE_CHECKING: reveal_type(Fiddle.print) fiddle = Fiddle() # !! Argument 1 to "__call__" of "Printer" has incompatible type "int"; expected "Fiddle" fiddle.print(12) fiddle.print() def mocked(self, value=None): print("Mocked answer:", value) with mock.patch.object(Fiddle, "print", autospec=True, side_effect=mocked): fiddle.print(12) fiddle.print()New mypy complaints:
test4.py:41: error: Argument 1 to "__call__" of "Printer" has incompatible type "int"; expected "Fiddle" [arg-type] test4.py:42: error: Missing positional argument "self" in call to "__call__" of "Printer" [call-arg] test4.py:50: error: Argument 1 to "__call__" of "Printer" has incompatible type "int"; expected "Fiddle" [arg-type] test4.py:51: error: Missing positional argument "self" in call to "__call__" of "Printer" [call-arg]What happens with class methods, is that the function object has a __get__ method that generates a bound versions of itself. Our Printer protocol does not define it, so mypy is now unable to type the bound method correctly.
Typing with Protocol, take 2So... we add the function descriptor methos to our Protocol!
A lot of this is taken from this discussion.
# Introduce typing, try with Protocol, harder! import functools from typing import TYPE_CHECKING, Protocol, TypeVar, Generic, cast, overload, Union from unittest import mock default = 42 A = TypeVar("A", contravariant=True) # We now produce typing for the whole function descriptor protocol # # See https://github.com/python/typing/discussions/1040 class BoundPrinter(Protocol): """Protocol typing for bound printer methods.""" def __call__(_, value: int | None = None) -> None: """Bound signature.""" class Printer(Protocol, Generic[A]): """Protocol typing for printer methods.""" # noqa annotations are overrides for flake8 being confused, giving either D418: # Function/ Method decorated with @overload shouldn't contain a docstring # or D105: # Missing docstring in magic method # # F841 is for vulture being confused: # unused variable 'objtype' (100% confidence) @overload def __get__( # noqa: D105 self, obj: A, objtype: type[A] | None = None # noqa: F841 ) -> BoundPrinter: ... @overload def __get__( # noqa: D105 self, obj: None, objtype: type[A] | None = None # noqa: F841 ) -> "Printer[A]": ... def __get__( self, obj: A | None, objtype: type[A] | None = None # noqa: F841 ) -> Union[BoundPrinter, "Printer[A]"]: """Implement function descriptor protocol for class methods.""" def __call__(_, self: A, value: int | None = None) -> None: """Unbound signature.""" def with_default(f: Printer[A]) -> Printer[A]: @functools.wraps(f) def wrapped(self: A, value: int | None = None) -> None: if value is None: value = default return f(self, value) return cast(Printer, wrapped) class Fiddle: # function has a __get__ method to generated bound versions of itself # the Printer protocol does not define it, so mypy is now unable to type # the bound method correctly @with_default def print(self, value: int | None = None) -> None: assert value is not None print("Answer:", value) fiddle = Fiddle() fiddle.print(12) fiddle.print() def mocked(self, value=None): print("Mocked answer:", value) with mock.patch.object(Fiddle, "print", autospec=True, side_effect=mocked): fiddle.print(12) fiddle.print()It works! It's typed! And mypy is happy!
This Week in KDE Apps
Welcome to a new issue of "This Week in KDE Apps"! Every week we cover as much as possible of what's happening in the world of KDE apps.
This week's changes and improvements cover a wide range of applications, from audio apps (including the classic Amarok, which is making a comeback) to Kate getting improvements to its integrated Git features.
In between, you have everything from new functionalities for note-taking utilities and media players, to upgrades in financial software and mobile apps.
Let's dig in!
Amarok A powerful music player that lets you rediscover your musicTuomas Nurmi worked on making the codebase Qt6-compatible. (Tuomas Nurmi, Link)
Ark Archiving ToolJin Liu disabled the "Compress to tar.gz/zip" service menu items in read-only directories. (Jin Liu, 24.12.0. Link)
Dolphin Manage your filesYou can now sort your videos by duration. (Somsubhra Bairi, 24.12.0. Link)
Eren Karakas added more standard actions (Sort By, View Mode, Cut and Copy) to the context menu in the trash view. (Eren Karakas, 24.12.0. Link)
Elisa Play music and listen to online radio stationsElisa now supports loading lyrics from .lrc files sitting alongside the song files. (Gary Wang, 24.12.0. Link)
Manuel Roth fixed the bug in which the metadata for webradio http streams was not getting displayed. (Manuel Roth, 24.12.0. Link)
Haruna Media playerYou now have the option to open videos in full screen mode. (Rikesh Patel, Link)
KDE Itinerary Digital travel assistantVolker Krause was at the OSM Hack Weekend last week and worked on the support of MOTIS v2 API support in the public transport client library used by KDE Itinerary. He also added a map view of an entire trip to Itinerary and the KPublicTransport demo application.
Kate Advanced Text EditorIn large repos, a git status update can be slow. The least we can do for the user is show that something is happening. Hence, now, if the git status is being refreshed you will see the refresh button become unclickable and start spinning. (Waqar Ahmed, 24.12.0. Link)
In the project tree view, files will now show their status in git. The status is shown minimally, i.e. via a small circle displayed in front of the file name. If the file has been modified, the circle is red; if the file is staged, it's green. (Waqar Ahmed, 24.12.0. Link)
We simplified the git panel by hiding the project combobox. The git panel will now show the status of the currently opened project. (Waqar Ahmed, 24.12.0. Link)
We fixed the SQL plugin's SQL export being randomly ordered. (Waqar Ahmed, 24.08.3. Link)
Clock Keep time and set alarmsKClock's timer now shows the remaining time instead of the elapsed time. (Zhangzhi Hu, 24.12.0. Link)
KMix Sound MixerWe fixed the Audio Setup button, which didn't open the System Settings Audio page correctly. (Sergio Basto, 24.12.0. Link)
KMyMoney Personal finance manager based on double-entry bookkeepingIt's once again possible to download stock quotes from yahoo.com after they changed their output format. (Ralf Habacker, Link)
Reports can now be exported as PDF and XML. (Ralf Habacker, KMyMoney 5.2.0. Link 1, link 2)
Photos Image GalleryWe improved the design of the properties panel. (Carl Schwan, 24.12.0. Link)
Kleopatra Certificate manager and cryptography appThe name of the "KWatchGnuPG" utility provided by Kleopatra has been updated to "GnuPG Log Viewer" (Carl Schwan, 24.12.0. Link) and we gave it a new logo.
KleverNotes Take and manage your notesKleverNotes' painting mode has been completely rewritten. It is now possible to add circles, rectangles, labels, and to choose the stroke size. The UI also uses a new floating toolbar. (Louis Schul, 1.2.0. Link)
We improved the animation when switching pages. (Luis Schul, 1.2.0. Link)
The note preview in the appearance settings was simplified to only show the important parts. (Luis Schul, 1.2.0. Link)
KMail A feature-rich email applicationFix a crash in the Exchange Web Services (EWS) backend. (Louis Moureaux, 24.08.3. Link)
KRDC Connect with RDP or VNC to another computerWe fixed sharing folders. (Fabio Bas, 24.08.3. Link)
Merkuro Calendar Manage your tasks and events with speed and easeClaudio Cambra fixed adding and creating sub-todos (Claudio Cambra, 24.08.3. Link and Link)) and a bug that made clicking on the month view unreliable. (Claudio Cambra, 24.08.3, Link).
We also added back the maps showing the location of individual events. This was disabled during the Qt6 migration and never enabled back afterwards. (Claudio Cambra, 24.08.3, Link)
NeoChat Chat on MatrixSupport for libQuotient 0.9 has been backported to NeoChat 24.08. This brings, among other things, cross-signing support and support for the Matrix 1.12 API, including most importantly content repo functionality switching to authenticated media. (James Graham, 24.08.0, Link)
Okular View and annotate documentsAlbert Astals fixed switching between pages in the single-page mode when using a mouse with a "high resolution" scroll wheel. (Albert Astals Cid, 24.12.0. Link)
You can now use any image type as a signature background. (Sune Vuorela, 24.12.0. Link)
We removed the last CHM support mention in Okular and on the website. CHM support was dropped when transitioning to the Qt6 version. (Albert Astals Cid, 24.12.0. Link 1, link 2)
Zanshin To Do Management ApplicationFixed an issue where projects would be displayed twice when toggling on and off their data source. (David Faure, 24.08.3. Link)
And all this too...Justin Zobel fixed various appstream files to use the new way of declaring the developer's name. (Justin Zobel, KRuler, Gwenview, KEuroCalc, ...)
We ported various projects to use declarative QML declaration for better maintainance and performance (Carl Schwan, Koko, Francis, Kalk).
... And Everything ElseThis blog only covers the tip of the iceberg! If you’re hungry for more, check out Nate's blog about Plasma and be sure not to miss his This Week in Plasma series, where every Saturday he covers all the work being put into KDE's Plasma desktop environment.
For a complete overview of what's going on, visit KDE's Planet, where you can find all KDE news unfiltered directly from our contributors.
Get InvolvedThe KDE organization has become important in the world, and your time and contributions have helped us get there. As we grow, we're going to need your support for KDE to become sustainable.
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 just keep KDE bringing Free Software to the world.
To get your application mentioned here, please ping us in invent or in Matrix.
Oliver Davies' daily list: A deep drive into test-driven Drupal development
Are you near London and want to learn about automated testing in Drupal?
I'll be presenting a session and Q&A on automated testing and test-driven development in Drupal.
This is one of my favourite topics to present and teach, so I'm looking forward to this event.
If you want to attend, RSVP on the meetup event page.
If you can't, check out my free Drupal testing email course or book a 1-on-1 consulting call and I'll get you started.
Drupal Core News: Drupal 11.1 alpha phase begins October 28; 11.1.0 to be released December 12-13
Drupal core typically has a minor release window the second week of December. This is to provide enough time after PHP and Symfony's release dates for core compatibility to be updated, but still far enough before the major end-of-year holidays to avoid interfering with vacations and travel.
This year, DrupalCon Singapore is scheduled for the same week as the minor release. Normally, we would avoid having a minor release the same week as a DrupalCon, but in this case we are unable to move the release date. We will aim to release 11.1.0 and 10.4.0 later in the week to avoid having the release during the actual days of the conference. The release window is now December 12-13 UTC.
Drupal 11.0 and 10.3 will continue to have security coverage until June 2025. So, it is safe for site owners to wait until January 2025 or later, if necessary, to update their sites.
Drupal 11.1 alpha phase begins October 28In preparation for the minor release, Drupal 11.1.x will enter the alpha phase the week of October 28, 2024. Core developers should plan to complete changes that are only allowed in minor releases prior to the alpha release. The 11.1.0-alpha1 deadline for most core patches is October 28, 2024.
The 10.5.x release branch of core will be created for the next maintenance minor release.
-
Developers and site owners can begin testing the alpha after its release.
-
The 11.1.x release branch of core will be created before the alpha is tagged. Future feature and API additions will continue to be targeted against 11.x.
-
After 11.1.x is branched but before 11.1.0-alpha1 is tagged, alpha experimental modules will be removed from the 11.1.x codebase. Their development will continue in 11.x only.
-
Following the release of Drupal 11.1 and 10.4, only security issues will be fixed in Drupal 11.0 and 10.3. Additionally, Drupal 10.2 will become end-of-life (EOL).
-
During the alpha phase, core issues will be committed according to the following policy:
- Most issues that are allowed for patch releases will be committed to 11.1.x and 10.4.x. Such issues may also be committed to 11.0.x and 10.3.x until the final normal bugfix releases of 11.0 and 10.3 on December 4, 2024.
- Most issues that are only allowed in minor releases will be committed to 11.x only. (Such issues may be released in 11.2 or another future minor.). A few strategic issues may be backported to 11.1.x, but only at committer discretion after the issue is fixed in 11.x (so leave them set to 11.x unless you are a committer), and only up until the beta deadline.
- Most issues that are allowed in maintenance minor releases will be committed to 11.x and 10.5.x only. A few strategic issues may be backported to 11.1.x and 10.4.x, but only at committer discretion after the issue is fixed in 11.x (so leave them set to 11.x unless you are a committer), and only up until the beta deadline.
Roughly two weeks after the alpha release, the first beta release will be created. All the restrictions of the alpha release apply to beta releases as well. The release of the first beta is a firm deadline for all feature and API additions. Even if an issue is pending in the Reviewed & Tested by the Community (RTBC) queue when the commit freeze for the beta begins, it will be committed to the next minor release only.
The release candidate phase will begin the week of November 25.
Security support of Drupal 10 and 11 Drupal 10.2.x Security releases will be provided until December 12, 2024. Drupal 10.3.x and 11.0.x Security releases will be provided until June 18, 2025.See the Drupal core release process overview, the Drupal core release schedule, allowed changes during the Drupal 10 and 11 release cycles, and Drupal 10 and 11 backwards compatibility and internal API policy for more information.