Feeds

Week 1 recap- research and prep

Planet KDE - Sun, 2024-06-02 20:57
Hi welcome to the blog. It's Week 1 and most of this time is allocated to researching and learning how the code base works. The main point is that I am trying to understand how exactly Krita "draws" aka puts polygons onto the canvas. Right now there ...
Categories: FLOSS Project Planets

Gizra.com: Private Composer Repos Using DDEV

Planet Drupal - Sun, 2024-06-02 20:00

We do not usually make use of private composer repos. The reason is simple, all our private code lives inside a single repo.

But sometimes, we need to re-use a project for multiple sites, and we still want to keep the code private. In those cases, a private composer repo makes sense.

Categories: FLOSS Project Planets

Amarok 3.0.1 released

Planet KDE - Sun, 2024-06-02 16:00

The Amarok Development Squad is happy to announce the immediate availability of Amarok 3.0.1, the first bugfix release for Amarok 3.0 "Castaway"

3.0.1 features a number of small improvements and bug fixes, the oldest fulfilled feature request dating back to 2010 this time. Wikipedia applet, UI strings, and playlist generation and collection filtering are among the components that have received multiple improvements in this release. The efforts to both further polish the Qt5/KF5 version, and keep doing clean-up and preparations that bring a Qt6/KF6 version closer, have been ongoing and will continue.

Changes since 3.0.0 FEATURES:
  • Added an option to copy image to clipboard in Wikipedia applet, and a clickable notification if a non-Wikipedia link was clicked.
  • Added an option to select if track's artist is shown for entries under various artists / different album artist in context browser (BR 276039, BR 248101)
  • Indicate which search option is active in Wikipedia applet (BR 332010)
CHANGES:
  • Amarok now depends on KDE Frameworks 5.78.
  • Improve strings in user interface (incl. BR 343896, BR 234854)
  • Reduce CPU usage by minimized/hidden analyzer (BR 390063) and other components.
BUGFIXES: Getting Amarok

In addition to source code, Amarok is available for installation from many distributions' package repositories, which are likely to update to 3.0.1 soon. A flatpak is currently available on flathub-beta.

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

Colin Watson: Free software activity in May 2024

Planet Debian - Sun, 2024-06-02 06:53

My Debian contributions this month were all sponsored by Freexian.

The bulk of my Debian time this month went towards trying to haul more Python packages up to current versions, but I got a few other bits and pieces done as well.

  • I did a little work on improving debbugs’ autopkgtest status.
  • openssh:
    • I fixed an OpenSSL version mismatch error in openssh-ssh1.
    • I finally tracked down a baffling CI issue in openssh, unblocking several contributed merge requests that I’d been sitting on until I could get CI to pass for them. (Special thanks to Andreas Hasenack; GSS-API integration tests will make my life much easier.)
    • I removed the user_readenv=1 option from openssh’s PAM configuration, and did some work on release notes to document this change for affected users.
    • I started work on the first stage of my plan to split out GSS-API key exchange support to separate packages.
  • Python team:
    • I upgraded bitstruct, flufl.enum, flufl.testing, gunicorn, langtable, psycopg3, pygresql, pylint-flask, python-click-didyoumean, python-gssapi, python-httplib2, python-json-log-formatter, python-persistent, python-pgspecial, python-pyld, python-repoze.tm2, python-serializable, python-tenacity, python-typing-extensions, python-unidiff, responses, shortuuid (including an upstream packaging tweak), sqlparse, vulture, zc.lockfile, and zope.interface to new upstream versions.
    • I cherry-picked an upstream PR to fix a pytest 8 incompatibility in ipywidgets.
  • I decided that fixing my old troffcvt package to support groff 1.23.0 wasn’t worth the time investment, and filed a removal request instead.
  • I NMUed bidentd and linuxtv-dvb-apps to declare Architecture: linux-any (and in the latter case also to fix a build failure due to 64-bit time), and worked with the buildd team to remove several of the other remaining entries from Packages-arch-specific.

You can support my work directly via Liberapay.

Categories: FLOSS Project Planets

Steinar H. Gunderson: SIMD detection of nested quotes

Planet Debian - Sun, 2024-06-02 06:10

I recently spent some time thinking about the problem of detecting quoted strings using SIMD, and I've come annoyingly close without actually having a practical solution; yet, I thought I would share my half-solution because I think it's fairly interesting in its own right.

To give a brief recap, here's an idealized version of the problem:

  • You have 16 (or whatever) ASCII bytes in a single SIMD register (SSE2, NEON, etc.).
  • Strings are delineated with "double quotes" or 'single quotes'.
  • Your task is, to efficiently as possible, make a value that is all-ones for each character within quotes and all-zeros everywhere else. (We don't care about what the mask says about the quotes themselves; that's easy to fix up afterwards anyway.)

The use, of course, is to be able to mask out special characters within strings. In my case, we were looking for the first right brace (}) in a byte stream, except that one wouldn't count those that were within quoted strings.

I'm going to recap first how to do this with only one kind of quotes; it's widely known, but I think it's useful to think about why it works. (There's also a variant based on carryless multiplication, which is now often efficient because CPUs implement them for cryptographic purposes, but I'm not going to go into it.) We'll then try to make an analogous solution that supports the harder case where quote markers can be within other quotes and themselves ignored. (For instance, in the string "quo'ted" not quoted "'", the “not quoted” part is between single quotes, but nevertheless, it should not be considered as quoted, because the single quote itself was quoted and thus ignored.)

If you only have one kind of quote (say, "), then the question for any given character is simply whether an odd number of quotes was before it. " turns on quoting, " turns off quoting again. This is computed most easily by comparing each character (in parallel) with ", and then XOR-ing the booleans as we go. This is called a prefix sum (just with XOR instead of add), and I'm going to write it out in full for eight bytes:

r7 = x7 ^ x6 ^ x5 ^ x4 ^ x3 ^ x2 ^ x1 ^ x0; r6 = x6 ^ x5 ^ x4 ^ x3 ^ x2 ^ x1 ^ x0; r5 = x5 ^ x4 ^ x3 ^ x2 ^ x1 ^ x0; r4 = x4 ^ x3 ^ x2 ^ x1 ^ x0; r3 = x3 ^ x2 ^ x1 ^ x0; r2 = x2 ^ x1 ^ x0; r1 = x1 ^ x0; r0 = x0;

So x0..x7 is whether each byte was a quote or not, and r0..r7 is whether we consider that byte quoted or not. (In the full problem, we'll need to consider whether we started our byte group in a quoted state or not, so technically, this only says whether each byte should invert the initial state or not. But for XOR, this is easy; just XOR in the initial value somewhere, either into x0 or into all of the r0..r7 as a post-processing step.)

For scalar code, there's a very simple and efficient way to compute this:

r0 = x0; r1 = r0 ^ x1; r2 = r1 ^ x2; r3 = r2 ^ x3; r4 = r3 ^ x4; r5 = r4 ^ x5; r6 = r5 ^ x6; r7 = r6 ^ x7;

However, this doesn't really work well for SIMD; we get one long dependency chain, with zero parallelism. We want to use those fancy ALUs for something. So instead, we can look at the expression and regroup it a bit:

r7 = (x7 ^ x6) ^ (x5 ^ x4) ^ (x3 ^ x2) ^ (x1 ^ x0); r6 = (x6 ^ x5) ^ (x4 ^ x3) ^ (x2 ^ x1) ^ x0; r5 = (x5 ^ x4) ^ (x3 ^ x2) ^ (x1 ^ x0); r4 = (x4 ^ x3) ^ (x2 ^ x1) ^ x0; r3 = (x3 ^ x2) ^ (x1 ^ x0); r2 = (x2 ^ x1) ^ x0; r1 = (x1 ^ x0); r0 = x0;

This hints that making some temporaries would be a useful step. Let's compute all of those pairs that we just created:

y7 = x7 ^ x6; y6 = x6 ^ x5; y5 = x5 ^ x4; y4 = x4 ^ x3; y3 = x3 ^ x2; y2 = x2 ^ x1; y1 = x1 ^ x0; y0 = x0;

This is very efficient to do in basically any SIMD instruction set; just shift the x0..x7 vector by 8 bits, and then do a XOR between the two vectors. (In some instruction sets, you may not have full 128-bit shifts available. It is fairly easy to work around at a slight loss in efficiency, so let's not bother ourselves with it.)

This allows us to rewrite our expression as:

r7 = y7 ^ y5 ^ y3 ^ y1; r6 = y6 ^ y4 ^ y2 ^ y0; r5 = y5 ^ y3 ^ y1; r4 = y4 ^ y2 ^ y0; r3 = y3 ^ y1; r2 = y2 ^ y0; r1 = y1; r0 = y0;

Hopefully, after staring a bit at this, you can see where we're going even though it's slightly different from before. We can make new parentheses and new temporaries and rewrite again:

z7 = y7 ^ y5; z6 = y6 ^ y4; z5 = y5 ^ y3; z4 = y4 ^ y2; z3 = y3 ^ y1; z2 = y2 ^ y0; z1 = y1; z0 = y0; r7 = z7 ^ z3; r6 = z6 ^ z2; r5 = z5 ^ z1; r4 = z4 ^ z0; r3 = z3; r2 = z2; r1 = z1; r0 = z0;

This is exactly the same, just shift by 16 bits instead of 8. And the last step is similarly easy.

Now, it's useful to thinking about what properties of our XOR operation we actually needed. Notably, we didn't need the property that XOR-ing something twice cancels out. And we didn't need that a ^ b = b ^ a (commutativity). Pretty much the only thing we needed was that our operation was associative ((a ^ b) ^ c = a ^ (b ^ c)) and that we could combine our elements before we knew the quoted state at the point in time, i.e. our values could be looked upon at an action on the state, and not manipulating the state directly until at later.

Now let's look at the more complicated example where we don't have just quoted/non-quoted, but three states for any byte. Let's number them:

  • 0: We are not within quotes.
  • 1: We are within double quotes.
  • 2: We are within single quotes.

For the purposes of the final answer, we don't really care about the difference between 1 and 2, but for figuring out the effect of any given input character, we definitely need to understand it. Let's look at a trivial character; call it c. It is not a quote, so what does it do in each of our states?

  • 0: Not within quotes, so we stay within quotes (stay in 0).
  • 1: In double quotes, so we are still within double quotes (stay in 1).
  • 2: In single quotes, so we are still within single quotes (stay in 2).

OK, so 0 → 0, 1 → 1, 2 → 2. Let's call that 012 for convenience of notation. What about the double-quote character "?

  • 0: Not within quotes, but after this, we are (move to 1).
  • 1: Within double quotes, so we're ending that (move to 0).
  • 2: Within single quotes, so the character is to be ignored (move to 2).

So double quotes gave rise to the mapping 0 → 1, 1 → 0, 2 → 2, or 102 for short. And we'll similarly find out that a single quote character ' will give the mapping 0 → 2, 1 → 1, 2 → 0, or 210 for short.

Now, the crucial insight comes: This is exactly like our XOR case! We can combine these without knowing what state we are in; just keep following the effect for all three states. For instance, the character sequence "x will trivially become 102 just like the double quote itself did. "x" will trivially become 012 (no effect). And we have some more interesting examples like "'; if we follow both maps in turn, we'll have 0 → 1 → 1, 1 → 0 → 2, 2 → 2 → 0. So this combination of signs will give is 120, or written out:

  • If we started with no quotes (0), we are now within double quotes (1).
  • If we started in double quotes (1), we are now in single quotes (2).
  • If we started in single quotes (2), we are now not in quotes (0).

Can we always do this? Yes! Group theory tells us that this is the symmetric group S₃. And groups are always closed (always return a new element of the group), and always associative. We know that S₃ has 3! = 6 elements, and it's not hard to construct examples of how to get into all 6 of them. We can label them 012 021 102 120 201 210, or we can give them easier-for-a-computer names like 0 1 2 3 4 5.

So that's the general battle plan. For each character, find out which state permutation it belongs to (one out of three). Then run the same cascade as before, just with the group product instead of XOR, given by the following table (trivially calculated by just following the states for each case; note that it is not symmetric, i.e., our group is nonabelian, but remember, we never required commutativity):

| 012 021 102 120 210 201 ----+------------------------ 012 | 012 021 102 120 210 201 021 | 021 012 201 210 120 102 102 | 102 120 012 021 201 210 120 | 120 102 210 201 021 012 210 | 210 201 120 102 012 021 201 | 201 210 021 012 102 120

or, equivalently with shorter names:

| 0 1 2 3 4 5 --+-------------- 0 | 0 1 2 3 4 5 1 | 1 0 4 5 2 3 2 | 2 3 0 1 5 4 3 | 3 2 5 4 0 1 4 | 4 5 1 0 3 2 5 | 5 4 3 2 1 0

and then finally combine with the status from the previous case. If we're in the 012 or 021 state (0 or 1), we're not within quotes for that character; otherwise, we are.

Now, of course, here's the problem: It's not obvious how to do this group product effieciently without a table. If we had only 16 elements, we could have used PSHUFB, but we have 36. When looking at the numeric variant, there are some values we could special-case (e.g. the entire first row and column), but e.g. the last row is only nearly trivial to calculate but not quite. So we'd be at an annoying amount of table lookups to get this to work.

So, that's where I stand. Faster than linear in theory, but probably less efficient in practice unless you had absolutely huge vectors and/or unusually efficient gather instructions. (I guess for an FPGA solution, this method wouldn't be so bad?) I didn't really bother trying to write up the actual code; I added some code to detect the difficult cases (they happen if any character thinks it's both within single quotes and double quotes at the same time) and error out if it were found, and then mostly called it a day. I guess the most efficient solution, if you really need to handle this case branch-free, would be a character-by-character one, but based on something like Sheng.

Edit: I noticed that there is actually a little respite; the group product table in this formulation is vertically antisymmetric (rows 0/5, 1/4 and 2/3 form pairs where one is 5-x of the other; some are also reverses of other rows, but that's perhaps less interesting), which makes it possible to do only two shuffles and then a lot of comparing and blending and fixup. I implemented it and it actually works, but is definitely too slow to be useful in practice. It seems there's also an AVX512 instruction that actually gives a 64-entry LUT, which would be really nice if it's fast, and well, if AVX512 actually existed everywhere. :-)

Categories: FLOSS Project Planets

Zato Blog: New API Integration Tutorial in Python

Planet Python - Sun, 2024-06-02 04:00
New API Integration Tutorial in Python 2024-06-02, by Dariusz Suchojad

Do you know what airports, telecom operators, defense forces and health care organizations have in common?

They all rely heavily on deep-backend software systems which are integrated and automated using principled methodologies, innovative techniques and well-defined implementation frameworks.

If you'd like to learn how to integrate and automate such complex systems correctly, head over to the new API integration tutorial that will show you how to do it in Python too.

# -*- coding: utf-8 -*- # Zato from zato.server.service import Service # ############################################################################## class MyService(Service): """ Returns user details by the person's name. """ name = 'api.my-service' # I/O definition input = '-name' output = 'user_type', 'account_no', 'account_balance' def handle(self): # For later use name = self.request.input.name or 'partner' # REST connections crm_conn = self.out.rest['CRM'].conn billing_conn = self.out.rest['Billing'].conn # Prepare requests crm_request = {'UserName':name} billing_params = {'USER':name} # Get data from CRM crm_data = crm_conn.get(self.cid, crm_request).data # Get data from Billing billing_data = billing_conn.post(self.cid, params=billing_params).data # Extract the business information from both systems user_type = crm_data['UserType'] account_no = crm_data['AccountNumber'] account_balance = billing_data['ACC_BALANCE'] self.logger.info(f'cid:{self.cid} Returning user details for {name}') # Now, produce the response for our caller self.response.payload = { 'user_type': user_type, 'account_no': account_no, 'account_balance': account_balance, } # ##############################################################################



API programming screenshots
➤ Here's the API integration tutorial again
➤ More API programming examples in Python

More blog posts
Categories: FLOSS Project Planets

Jacob Adams: What to Do When You Forget Your Root Password

Planet Debian - Sat, 2024-06-01 20:00

Forgetting your root password would initially seem like a problem requiring a full re-install, one that you can’t easily recover from without wiping everything away.

Forgetting your user password can of course be solved by changing it as root, as in the following, which changes the password for user jacob:

# passwd jacob

but only the root user can change their own password, so you need to somehow get root access in order to do so.

Changing Root’s Password with Sudo

This one is probably obvious, but if you have a user with the ability to use sudo, then you can change root’s password without access to the root account by running:

$ sudo passwd

which will reset the password for the root account without requiring the existing password.

Boot Directly to a Shell

Getting root access to any Linux machine you have physical access to is surprisingly simple. You can just boot the machine directly into a root shell without any access control, i.e. passwords.

Why You Should Always Encrypt Your Storage1

To boot directly to a shell you need to append the following text to the kernel command line:

init=/bin/sh

(You could use pretty much any program here, but you’re putting your system into a weird state doing this, and so I’d recommend the simplest approach.)

GRUB

GRUB will allow you to edit boot parameters on startup using the e key. You’ll then be presented with a editor2 that you can use to change the kernel command line by appending to the linux line.

E.g. If your editor looks like this:

load_video insmod gzio if [ x$grub_platform = xxen ]; then insmod xzio; insmod lzopio; fi insmod part_gpt insmod ext2 search --no-floppy --fs-uuid --set=root abcd1234-5678-0910-1112-abcd12345678 echo 'Loading Linux 6.1.0-21-amd64 ...' linux /boot/vmlinuz-6.1.0-21-amd64 root=UUID=abcd1234-5678-0910-1112-abcd12345678 ro quiet echo 'Loading initial ramdisk ...' initrd /boot/initrd.img-6.1.0-21-amd64

Then you would add init=/bin/sh like so:

load_video insmod gzio if [ x$grub_platform = xxen ]; then insmod xzio; insmod lzopio; fi insmod part_gpt insmod ext2 search --no-floppy --fs-uuid --set=root abcd1234-5678-0910-1112-abcd12345678 echo 'Loading Linux 6.1.0-21-amd64 ...' linux /boot/vmlinuz-6.1.0-21-amd64 root=UUID=abcd1234-5678-0910-1112-abcd12345678 ro quiet init=/bin/sh echo 'Loading initial ramdisk ...' initrd /boot/initrd.img-6.1.0-21-amd64

Once you’ve edited it you can start your machine with Ctrl+x, as you can see from the prompt text under the editor.

Raspberry Pi cmdline.txt

On a Raspberry Pi you’ll want to append the above to only line of the cmdline.txt file on the boot partition of the SD card. This is the first partition of the disk, the one that is FAT32.

You’ll need to do this on another machine, since if you had root access to edit cmdline.txt you could also just change your password.

As it is a FAT32 partition on an SD card, it should be editable on any other machine that supports SD cards.

E.g. If your cmdline.txt looks like this

console=serial0,115200 console=tty1 root=PARTUUID=fb33757d-02 rootfstype=ext4 fsck.repair=yes rootwait quiet

Then you would add init=/bin/sh like so:

console=serial0,115200 console=tty1 root=PARTUUID=fb33757d-02 rootfstype=ext4 fsck.repair=yes rootwait quiet init=/bin/sh Mount Read / Write

Since you’re replacing the init process of the machine with a shell, no other processes will be running.

Also, your root filesystem will be mounted read-only, as init is expected to remount it read-write as needed.

# mount -o remount,rw / Change Root Password

Once you’ve remounted the root filesystem, all that’s needed is to run the passwd command.

# passwd

Since you’re running the command as root you won’t need to provide your existing password, and will only need to type a new password twice.

Now of course you simply need to remember that password in order to ensure you don’t need to do this again.

Reboot Safely

You now cannot follow the standard reboot process here, as you’re only running one process.

Therefore it’s important to put your root filesystem back into read-only before powering off your machine:

# mount -o remount,ro /

Once you’ve done that you just need to hold down the power button until the machine completely powers off or pull the plug.

And then you’re done! Boot the computer again and you’ll have everything working as normal, with a root password you remember.

  1. Not that this is the only reason, anyone with physical access to your machine could also boot it into another operating system they control, or just remove your storage device and put it into another computer, or probably other things I’m not thinking of now. You should always encrypt your devices. 

  2. The editor uses emacs-like keybindings. The manual includes a list of all the options available. 

Categories: FLOSS Project Planets

Mario Hernandez: Automating your Drupal Front-end with ViteJS

Planet Drupal - Sat, 2024-06-01 20:00

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

NOTE: The project covered in this post does not use Single Directory Components nor the Storybook module. 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.

  • Finally, since we updated our project structure earlier, let's update the rollupOptions' input path within the Twig build object configuration:
build: { emptyOutDir: true, outDir: 'dist', rollupOptions: { input: glob.sync(path.resolve(__dirname,'./src/components/**/*.{css,js}')), output: { assetFileNames: 'css/[name].css', entryFileNames: 'js/[name].js', }, }, },

Fig. 11: Twig plugin with updated input path.

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. 12: 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. 13: 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. 14: 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. 15: 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. 16: 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. Pretty sweet! 🍰

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

findutils @ Savannah: GNU findutils 4.10.0 released

GNU Planet! - Sat, 2024-06-01 14:30

This is to announce findutils-4.10.0, a stable release.
See the NEWS below for more details.

GNU findutils is a set of software tools for finding files that match
certain criteria and for performing various operations on them.
Findutils includes the programs "find", "xargs" and "locate".
More information about findutils is available at:
  https://www.gnu.org/software/findutils/

Please report bugs and problems with this release via the the
GNU Savannah bug tracker:
  https://savannah.gnu.org/bugs/?group=findutils

Please send general comments and feedback about the GNU findutils
package to the mailing list (<mailto:bug-findutils@gnu.org):
  https://lists.gnu.org/mailman/listinfo/bug-findutils

There have been 88 commits by 8 people in the - sigh - 121 weeks since 4.9.0:
  Antonio Diaz Diaz (2)       James Youngman (24)
  Bernhard Voelker (57)       John A. Leuenhagen (1)
  Bjarni Ingi Gislason (1)    Shuiqing Zhou (1)
  Helmut Grohne (1)           ribbon (1)

This release was bootstrapped with the following tools:
   Autoconf 2.72
   Automake 1.16.5
   M4 1.4.18
   Gnulib v1.0-187-g623bcc22f4

Please consider supporting the Free Software Foundation in its fund
raising appeal; see <https://www.fsf.org/appeal/>.

Thanks to everyone who has contributed!

Have a nice day,
Bernhard Voelker [on behalf of the GNU findutils maintainers]

================================================================================

Here are the compressed sources:
  https://ftp.gnu.org/pub/gnu/findutils/findutils-4.10.0.tar.xz
   
Here are the GPG detached signatures[*]:
  https://ftp.gnu.org/pub/gnu/findutils/findutils-4.10.0.tar.xz.sig

Use a mirror for higher download bandwidth:
  http://www.gnu.org/order/ftp.html

Here is the SHA256 checksum:
 
  1387e0b67ff247d2abde998f90dfbf70c1491391a59ddfecb8ae698789f0a4f5  findutils-4.10.0.tar.xz

[*] Use a .sig file to verify that the corresponding file (without the
.sig suffix) is intact.  First, be sure to download both the .sig file
and the corresponding tarball.  Then, run a command like this:

gpg --verify findutils-4.10.0.tar.xz.sig

If that command fails because you don't have the required public key,
then run this command to import it:

gpg --keyserver keys.gnupg.net --recv-keys A5189DB69C1164D33002936646502EF796917195

and rerun the 'gpg --verify' command.

================================================================================

NEWS

  • Noteworthy changes in release 4.10.0 (2024-06-01) [stable]


** Bug Fixes

  Find now defaults to optimization level 1 rather than 2 and the
  cost-based optimizer will only run at level 2 and above.  This
  should prevent changes of operation order which result in
  user-visible differences in behaviour. [#58427]

  If the -P option to xargs is not used, xargs will not change the way
  in which the SIGUSR1 and SIGUSR2 signals are handled.  This means
  that they will cause the program to terminate if the signals were
  not ignored in the process which started xargs.  This also means that
  xargs does not use parallel execution at all.
  If you start xargs with '-P 1', then xargs will not be killed by these
  signals, and they instead change the degree of parallelism.
  This change improves xargs' POSIX compliance.

  'xargs -P' now waits for all its child processes to complete before
  exiting, even if one of them exits with status 255. [#64451]

  If the -P option of xargs is in use, reads on standard input which are
  interrupted by a signal are re-started. [#64442]

  'find -name /' no longer outputs a warning, because that is a valid pattern
  to match the root directory "/".  Previously, a diagnostic falsely claimed
  that this pattern would not match anything. [#62227]

  'find -gid' (without the mandatory argument) now outputs a correct error
  diagnostic.  Previously it output: "find: invalid argument `-gid' to `-gid'".
  The error diagnostic for non-numeric arguments has been improved as well.
  Likewise for -inum, -links and -uid.

  'find -user' and 'find -group' now allow to specify larger UIDs/GIDs.
  Previously, that was limited to INT_MAX, although the types uid_t and gid_t
  are larger on many systems, including x86_64 GNU/Linux. [#64900]

  'find -xtype l' no longer fails on symbolic links that point to
  themselves.  These are treated similarly to broken links. [#51926]

** Improvements

  The find predicates -used, -amin, -cmin, -mmin, -atime, -ctime, and -mtime
  now properly diagnose a not-a-number argument.  Previously, find dumped
  core via an assertion.  [#64717]

** Changes to the build process

  findutils now builds again on systems with musl-libc.
  This requires gettext-0.19.8.

  findutils programs no longer fail for timestamps past the year 2038
  on obsolete configurations with 32-bit signed time_t, because the
  build procedure now rejects these configurations.
  On systems without any year2038 support configure with --disable-year2038.

** Documentation Changes

  When generating the Texinfo manual, `makeinfo` is invoked with the --no-split
  option for all output formats now; this avoids files like find.info-[12].

  The xargs documentation now describes the double dash "--" option delimiter.

  The xargs examples in the Texinfo manual now use the -L and --replace options
  instead of the deprecated -l and -i options.  [#64480]

  The TexInfo manual now uses upper-case 'B' as birthtime for the -newerXY
  comparison consistently.  [#65378]

** Translations

Updated the following translations: Belarusian, Brazilian Portuguese,
Bulgarian, Catalan, Chinese (simplified), Chinese (traditional),
Croatian, Czech, Danish, Dutch, Esperanto, Estonian, Finnish, French,
Galician, Georgian, German, Greek, Hungarian, Indonesian, Irish,
Italian, Japanese, Korean, Lithuanian, Luganda, Malay, Norwegian
Bokmaal, Polish, Portuguese, Romanian, Russian, Serbian, Slovak,
Slovenian, Spanish, Swedish, Turkish, Ukrainian, Vietnamese.

Categories: FLOSS Project Planets

Guido Günther: Free Software Activities May 2024

Planet Debian - Sat, 2024-06-01 13:17

A short status update of what happened on my side last month. A broken gcovr in Debian triggered a bit of busy work but 0.39.0 came out nicely nevertheless. We also reduced build time quiet a bit in phosh and phoc.

If you want to support my work see donations.

Categories: FLOSS Project Planets

Ian Jackson: What your vote is worth - a back of the envelope calculation

Planet Debian - Sat, 2024-06-01 05:40

tl;dr: Your vote really counts!

Each vote in a UK General Election is worth maybe £100,000 - to you and all your fellow citizens taken together. If you really care about the welfare of everyone affected by actions of the UK government, then it’s worth that to you too.

Introduction

It seems a common perception that one vote, in amongst all those millions, doesn’t really matter. So maybe it’s not worth voting. But, voting is (largely) what determines what the government does - and the government is big. It’s as big as all the people.

If you are the kind of person who cares about what happens to everyone in your polity and indeed everyone its actions affect, then even your one vote is very important indeed.

A method for back of the envelope calculation

It would be nice to give a quantitative estimate. Many things in our society are measured in money, so let’s try taking a stab at calculating the money value of your vote.

The argument I’m going to make is this: the government (by which I include the legislature), which is selected by our votes, decides how to spend the national budget.

So, basically, I’m going to divide the budget, by the electorate.

UK Parliament

UK Parliamentary elections decide not only the House of Commons, but, through that, the government. The upper house, the House of Lords, has very limited influence. So I think it’s fair to regard the Parliamentary election as, simply, controlling that budget.

Being lazy, I’m going to use Wikipedia data. We have the size of the electorate, for 2019, 47.6 million. But your influence isn’t shared with the whole electorate, only with the other people who also vote. Turnout in 2019 was 67.3%. The 2019 budget isn’t listed but I’ll just average the 2018 and March 2020 figures £842bn and £873bn, so £857 billion. (Strictly speaking I should add up the budgets for the period of the Parliament, but that seems like a lot of effort.)

There’s a discrepancy in the timescale we need to account for. Your vote influences the budgets for several years, depending how long it is until the next election. Taking Wikipedia’s list of elections this century there’ve been 7 in 24 years. So that’s an average of about 3.4y.

So, multiplying it through, we have (£857b * (24 / 7)) / (47.6M * 67.3%), giving a guess at the value of your UK General Election vote:

£92,000.

European Parliament

2022 budget for the European Union (Wikipedia again) was €170.6 bn.

The last election, in 2019, had a turnout of 198,352,638. Each EU Parliament lasts 5 years.

The Parliament, however, shares responsibility for the budget with the European Council, which is controlled, ultimately, by national governments. We have to pick a numerical value for the Parliament’s share of the influence. Over the past years the Parliament has gradually been more willing to exercise its powers in this area. I’m going to arbitrarily call its share 50%.

The calculation, then, is €170.6 bn * 5 * 50% / 198M, giving a guess at the value of your EU Parliamentary Election vote:

€2150.

This much smaller figure reflects simply that the EU doesn’t spend very much money, for a polity of its size. (Those stories in the British press giving the impression that the EU is massively wasteful are, simply, lies.)

The interaction of this calculation with the Council’s share of the influence, and with national budgets, is a bit of a question, but given the much smaller amounts involved, it doesn’t seem worth thinking about that too hard.

Only if you care about other people as much as yourself!

All of this is only true for you if you value and want to help everyone in your society. That includes immigrants, women, unemployed people, disabled people, people who are much poorer or richer than you, etc.

If you think about it in purely personal terms, your vote is hardly worth anything - because while the effect of your vote, overall, is very large, that effect is shared by everyone in your polity. So if you only care about yourself, voting is a total waste of time. The more selfish and xenophobic and racist and so on you are - caring only about people like yourself - the less your vote is worth.

This is why voting is rightly seen as a civic duty. I just spent £30 to courier my EP vote to Den Haag. That only makes sense because I’m very willing to spend that £30 to try to improve the spending of the €2000 or so that’s my share of the EU budget.

This is a very rough analysis

These calculations neglect a lot of very important things: politics isn’t just about the allocation of resources. It’s also about values, and bad politics can seriously harm people.

Arguably many of those effects of your vote, are much more important than just how the budget is set and spent.

It would be interesting to see an attempt at a similar analysis but for taking into account life and death questions like hate crime, traffic violence, healthcare, refugees’ welfare, and so on. I’m not sure how to approach that. Maybe some real social scientists have done so? References welcome.

Also, even on its own terms, this analysis is very rough and ready. We haven’t modelled the ability of the government to change its tax rates; perhaps we should be multiplying GDP (or some other better measure) by 90% percentile total tax rate amongst “countries like this one”. The amount of influence that can be wielded by one vote is probably nonlinear in the size of the political faction, but IDK in which direction. In unfair voting systems like the UK’s, some people’s votes are worth much more than others. In a very marginal constituency, which is a target seat, your vote might be worth tens of millions. In a safe seat, it might “only” be worth a few thousand. And in practical terms you don’t get to choose precisely the policies you want; you have to pick a party, which is sometimes very much a question of the lesser evil.

So, there is much I haven’t modelled. But the key point stands:

Conclusion

Although your vote is diluted by everyone else’s votes, together, we control the government, which affects us all. So if you care about the whole of society, the big numbers in the divisor, and the numerator, cancel out.

You can think of your vote as controlling one citizen’s worth of government activity.

edited 2024-06-01 09:40 Z to fix a grammar botch



comments
Categories: FLOSS Project Planets

Tryton News: Newsletter May 2024

Planet Python - Sat, 2024-06-01 02:00

During the last month we focused on fixing bugs, improving the behaviour of things, speeding-up performance issues - building on the changes from our last release. We also added some new features which we would like to introduce to you in this newsletter.

For an in depth overview of the Tryton issues please take a look at our issue tracker or see the issues and merge requests filtered by label.

Changes for the User CRM, Sales, Purchases and Projects

We’ve moved the language field on the party form to the header.

Accounting, Invoicing and Payments

Tryton now ensures the payment amount is greater than zero.

Stock, Production and Shipments

We’ve added a code with a sequence to the production bill of materials (BOM) to clearly distinguish similarly named BOMs.

We’ve also added a shipped state to the customer shipments.
The shipped-state becomes handy when the delivery process takes a long time.
After being packed now the delivery can become shipped or done (similar to internal and drop-shipments). The transition packed → shipped will delete the staging outgoing moves.

As stock lots are not associated with a company, we now ensure that sequences used to generate their numbers are not be linked to a specific company to avoid access right errors.

User Interface

We updated the TinyMCE in Sao to version 7 (see external changelog).

In all of our Tryton clients the user can now close tabs by clicking on them using the middle mouse button.

To avoid accidentally changing configuration values for external services, we now raise a confirmation warning when changing the credential settings in the following modules:

  • account_payment_braintree
  • account_payment_stripe
more… (click for more details) System Data and Configuration

We’ve standardized the format of pictures used in Tryton. Product and avatar images are converted to RGB with a resolution of 300 DPI, so we can rely on a consistent printed size.

We added a description field to the product image which can be used as the alt property on websites.

Now reports in Tryton can be printed with a company logo in PNG-format (for transparency support).

New Documentation

We added section anchors to each option of the configuration documentation. To refer to the docs of an option, you can now use e.g. Email settings <config-email>.

New Releases

We released bug fixes for the currently maintained long term support series
7.0 and 6.0, and for the penultimate series 6.8.

Changes for the System Administrator

The logging messages generated by modules and the bus have been unified.

The CSV import now handles the :lang= suffix when it is appended to a translatable field name.

Changes for Implementers and Developers

We’ve added partial support for the Unique and Exclude constraints in the SQLite backend with UNIQUE INDEX as long as they do not use parameters.

A python-format flag is now added to the PO-files.

Authors: @dave @pokoli @udono

1 post - 1 participant

Read full topic

Categories: FLOSS Project Planets

Russ Allbery: Review: I Shall Wear Midnight

Planet Debian - Sat, 2024-06-01 00:29

Review: I Shall Wear Midnight, by Terry Pratchett

Series: Discworld #38 Publisher: Harper Copyright: 2010 Printing: 2011 ISBN: 0-06-143306-3 Format: Trade paperback Pages: 355

I Shall Wear Midnight is the 38th Discworld novel and the 4th Tiffany Aching novel. This is not a good place to start reading.

Tiffany has finished her training and has returned to her home on the Chalk, taking up her duties as the local witch. There are a lot of those, because there's a lot that needs doing. In some cases, such as taking away the pain of the old Duke, they involve things that require magic and that only Tiffany can do. In many other cases, other people could pick up some of the work, but they lack Tiffany's sense of duty and willingness to pay attention.

The people of the Chalk have always been a bit suspicious of witches, in part because the job was done for so long by Tiffany's grandmother and no one thought she was a witch. (She was a witch.) Of late, however, that suspicion seems to be getting worse. It comes to a head when Tiffany is accused of theft and worse by the old Duke's maid, a woman with very fixed ideas about the evils of witches. Tiffany has to sort out what's going on and clear herself, all while navigating her now-awkward relationship with the Duke's son Roland, his unimpressive fiancee, and his spectacularly annoying aunt.

Ah, this is the stuff. This is exactly the Tiffany Aching novel that I have been hoping Pratchett would write. It's pure, snarky competence porn from start to finish.

"I'm a witch. It's what we do. When it's nobody else's business, it's my business."

One of the things that I adore about this series is how well Pratchett shows the different ways in which one can be a witch. Granny Weatherwax out-thinks everyone and nudges (or shoves) people in the right direction, but her natural tendency is to be icy and a bit frightening. Nanny Ogg is that person you can't help but talk to, who may seem happy-go-lucky and hedonistic but who can effortlessly change the mood of a room. And Tiffany is stubborn duty and blunt practicality, which fits the daughter of shepherds. In previous books, we've watched Tiffany as a student, learning the practicalities of being a witch. This is the book where she realizes how much she knows and how much easier the world is to navigate when she's in her own territory.

There is a wonderful scene, late in this book, where Pratchett shows Nanny Ogg at her best, doing the kinds of things that only Nanny Ogg can do. Both Tiffany and the reader are in awe.

I should have learned this, she thought. I wanted to learn fire, and pain, but I should have learned people.

And it's true that Nanny Ogg can do things that Tiffany can't. But what makes this book so great is that it shows how Tiffany's personality and her training come together with her knowledge of the Chalk. She may not know people, in general, but she knows her neighbors and how they think. She doesn't manage them the way that Nanny Ogg would; she's better at solving different kinds of problems, in different ways. But they're the right ways, and the right problems, for her home.

This is another Discworld novel with a forgettable villain that's more of a malevolent force of nature than a character in its own right. It's also another Discworld novel where Pratchett externalizes a human tendency into a malevolent force that can possess people. I have mixed feelings about this narrative approach. That externalization of evil into (in essence) demons has been repeatedly used to squirm out of responsibility and excuse atrocities, and it neatly avoids having to wrestle with the hard questions of prejudice and injustice and why apparently good people do awful things.

I think some of those weaknesses persist even in Pratchett's hands, but I think what he was attempting with that approach in this book is to show how almost no one is immune to nastier ideas that spread through society. Rather than using the externalization of evil as an excuse, he's using it as a warning. With enough exposure to those ideas, they start sounding tempting and partly credible even to people who would never have embraced them earlier. Pratchett also does a good job capturing the way prejudice can start from thoughtless actions that have more to do with the specific circumstances of someone's life than any coherent strategy.

Still, the one major complaint I have about this book is that the externalization of evil is an inaccurate portrayal of the world, and this catches up with Pratchett at the ending. Postulating an external malevolent force reduces evil to something that can be puzzled out and decisively defeated, thus resolving the problem. Sadly, this is not how humans actually work.

I'll forgive that structural flaw, though, because the rest of this book is so good. It's rare that a plot twist in a Discworld novel surprises me — twisty plots are not Pratchett's strength — but this one did. I will not spoil the surprise, but one of the characters is not quite who they seem to be, and Tiffany's reactions once she figures that out are one of my favorite parts of this book. Pratchett is making a point about assumptions, observation, and the importance of being willing to change one's mind about someone when you know more, and I thought it was very well done.

But, most of all, I enjoyed reading about Tiffany being calm, competent, determined, and capable. There's also a bit of an unexpected romance plot that's one of my favorite types: the person who notices that you're doing a lot of work and quietly steps in and starts helping while paying attention to what's needed and not taking over. And it's full of the sort of pithy moral wisdom that makes Discworld such a delight to read.

"There have been times, lately, when I dearly wished that I could change the past. Well, I can't, but I can change the present, so that when it becomes the past it will turn out to be a past worth having."

This was just what I wanted. Highly recommended.

Followed by Snuff in publication order. The next (and last, sadly) Tiffany Aching book is The Shepherd's Crown.

Rating: 9 out of 10

Categories: FLOSS Project Planets

Russell Coker: Links May 2024 (late)

Planet Debian - Fri, 2024-05-31 21:42

VoltageDivide has an interesting article on Unconventional Uses of FPGAs [1]. Tagline – Every sensor is a temperature sensor, nearly everything is a resistor or a conductor if you try hard enough and anything is an antenna. Datasheets are just a suggestion, and finally, often we pretend things are ideal, when they often are not.

Interesting blog post about the way npm modules that depend on everything exposed flaws in the entire npm system [2]. The conclusion should have included “use a fake name for doing unusual tests”.

Krebs on Security has an interesting article about MFA bombing [3]. Looks like Apple has some flaws in their MFA system, other companies developing MFA should learn from this.

Joey wrote an informative blog post about the Vultr hosting company wanting to extract data from VMs run for clients to train ML [4]. If your email is stored on such a VM it could be “generated” by an AI system.

John Goerzen wrote an interesting post looking at the causes of the xz issue from a high level [5].

Interesting article about self proclaimed Autistic pro-natalists [6]. They seem somewhat abusive to their kids and are happy to associate with neo-Nazis. :(

Joey Hess wrote an interesting blog post about the possibility of further undiscovered attacks on xz [7]. Going back to an earlier version seems like a good idea.

The Guardian has an interesting article about Amazon’s 2 pizza rule and the way the company is structured [8]. It’s interesting how they did it, but we really need to have it broken up via anti-trust legislation.

John Goerzen wrote an informative post about Facebook censorship and why we should all move to Mastodon [9]. Facebook needs to be broken up under anti-trust laws.

Kobold Letters is an attack on HTML email that results in the visual representation of email changing when it is forwarded. [10]. You could have the original email hide some sections which are revealed with the recipient forwards it for a CEO impersonation attack.

Related posts:

  1. Links January 2024 Long Now has an insightful article about domestication that considers...
  2. Links March 2024 Bruce Schneier wrote an interesting blog post about his workshop...
  3. Links April 2024 Ron Garret wrote an insightful refutation to 2nd amendment arguments...
Categories: FLOSS Project Planets

Junichi Uekawa: June already.

Planet Debian - Fri, 2024-05-31 20:56
June already. Thinking about what to do in Debconf.

Categories: FLOSS Project Planets

Git quality of life (2)

Planet KDE - Fri, 2024-05-31 18:00

Here’s another minor git convenience which I’m blogging as a letter to my future self who needs to look it up again: git log with the filenames included, and git log with a bit of graphical annotation for the history structure.

These are just my brief notes. If you want a beautifully readable introduction to git, I suggest Julia EvansHow Git Works”.

Git commands have just so many options, so I can never remember what is what, but here are two alias entries from my ~/.gitconfig: They stand for file log and graph log, respectively.

[alias] flog = log --name-status glog = log --oneline --decorate --graph

With these aliases, git flog produces a log which lists the affected files and their status (added, modified, deleted, …) for each commit, which is nice for the “what files did I touch then?” question.

For a compact view, git glog only provides the one-line-summary message and tries to draw a history graph. In the case of linear history, that comes down to starting each line with a *, but git alligator history is a little more decorated – but still readable.

Categories: FLOSS Project Planets

Dirk Eddelbuettel: RcppArmadillo 0.12.8.4.0 on CRAN: Upstream Bugfix

Planet Debian - Fri, 2024-05-31 17:57

Armadillo is a powerful and expressive C++ template library for linear algebra and scientific computing. It aims towards a good balance between speed and ease of use, has a syntax deliberately close to Matlab, and is useful for algorithm development directly in C++, or quick conversion of research code into production environments. RcppArmadillo integrates this library with the R environment and language–and is widely used by (currently) 1151 other packages on CRAN, downloaded 34.6 million times (per the partial logs from the cloud mirrors of CRAN), and the CSDA paper (preprint / vignette) by Conrad and myself has been cited 584 times according to Google Scholar.

Conrad released a new upstream bugfix yesterday (to improve views of sparse matrices). We uploaded it yesterday too but it once agfain took a day for the hard-working CRAN maintainers to concur that the two NOTEs from reverse-dependency checking over 1100 packages were in a fact false positves. And so it appeared on CRAN earlier today. We also increased the versioned dependency on Rcpp to match the use of optional entry-point headers Rcpp/Light, Rcpp/Lighter and Rcpp/Lightest. No other changes were made.

The set of changes since the last CRAN release follows.

Changes in RcppArmadillo version 0.12.8.4.0 (2024-05-30)
  • Upgraded to Armadillo release 12.8.4 (Cortisol Injector)

    • Faster handling of sparse submatrix views
  • Update versioned Depends on Rcpp to 1.0.8 or later to match use of Light/Lighter/Lightest headers.

Courtesy of my CRANberries, there is a diffstat report relative to previous release. More detailed information is on the RcppArmadillo page. Questions, comments etc should go to the rcpp-devel mailing list off the Rcpp R-Forge page.

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

No TWiK this week

Planet KDE - Fri, 2024-05-31 13:23

We’ll be back next week!

Categories: FLOSS Project Planets

Bits from Debian: New Debian Developers and Maintainers (March and April 2024)

Planet Debian - Fri, 2024-05-31 12:00

The following contributors got their Debian Developer accounts in the last two months:

  • Patrick Winnertz (winnie)
  • Fabian Gruenbichler (fabiang)

The following contributors were added as Debian Maintainers in the last two months:

  • Juri Grabowski
  • Tobias Heider
  • Jean Charles Delépine
  • Guilherme Puida Moreira
  • Antoine Le Gonidec
  • Arthur Barbosa Diniz

Congratulations!

Categories: FLOSS Project Planets

mark.ie: My LocalGov Drupal contributions for week-ending May 31th, 2024

Planet Drupal - Fri, 2024-05-31 12:00

Here's what I've been working on for my LocalGov Drupal contributions this week. Thanks to Big Blue Door for sponsoring the time to work on these.

Categories: FLOSS Project Planets

Pages