Andrew Cater: Building a mirror of various Red Hat oriented "stuff"

Planet Debian - Wed, 2023-08-30 14:43
Building a mirror for rpm-based distributions.

I've already described in brief how I built a mirror that currently mirrors Debian and Ubuntu on a daily basis. That was relatively straightforward given that I know how to install Debian and configure a basic system without a GUI and the ftpsync scripts are well maintained, I can pull some archives and get one pushed to me such that I've always got up to date copies of Debian and Ubuntu.

I wanted to do something similar using Rocky Linux to pull in archives for Almalinux, Rocky Linux, CentOS, CentOS Stream and (optionally) Fedora.

(This was originally set up using Red Hat Enterprise Linux on a developer's subscription and rebuilt using Rocky Linux so that the machine could be passed on to someone else if necessary. Red Hat 9.1 has moved to x86_64v2 - on the machine I have (HP Microserver gen 8) 9.1 it fails immediately. It has been rebuilt to use Rocky 8.8).

This is a minimal install of Rocky as console only - the machine it's on only has 4G of memory so won't run a GUI reliably. It will run Cockpit so can  be remotely administered. One user to run everything - mirror.

Minimal install of Rocky 8.7 from DVD .iso. SELinux is enabled, SSH works for remote access. SELinux had to be tweaked to allow /srv/ the appropriate permissions to be served by nginx. /srv is a large LVM volume rather than a RAID 6 - I didn't have enough disks

Adding nginx, enabling Cockpit and editing the Rocky Linux mirroring scripts resulted in something straightforward to reproduce.

nginxI cheated and stole large parts of my Debian config. The crucial part to remember is that there is no autoindexing by default and I had to dig to find the correct configuration snippet.

  # Load configuration files for the default server block.

        include /etc/nginx/default.d/*.conf;

        location / {
                autoindex on;
                autoindex_exact_size off;
                autoindex_format html;
                autoindex_localtime off;
                # First attempt to serve request as file, then
                # as directory, then fall back to displaying a 404.
                try_files $uri $uri/ =404;
 Rocky Linux mirroring scriptsSystemd unit file for service

Description=Rocky Linux Mirroring script



 Rocky linux  timer file

Description=Run Rocky Linux mirroring script daily

OnCalendar=*-*-* 08:13:00
OnCalendar=*-*-* 22:13:00


Mirror script#!/bin/env bash
# mirrorsync - Synchronize a Rocky Linux mirror
# By: Dennis Koerner <koerner@netzwerge.de>
# The latest version of this script can be found at:
# https://github.com/rocky-linux/rocky-tools
# Please read https://docs.rockylinux.org/en/rocky/8/guides/add_mirror_manager
# for further information on setting up a Rocky mirror.
# Copyright (c) 2021 Rocky Enterprise Software Foundation

This is a very long script in total.

Crucial parts I changed only listed the mirror to pull from and the place to put it.

# A complete list of mirrors can be found at
# https://mirrors.rockylinux.org/mirrormanager/mirrors/Rocky

# Your local path. Change to whatever fits your system.
# $mirrormodule is also used in syslog output.


 Logfile looks something like this: the single time spec file is used to check whether another rsync needs to be run

deleting 9.1/plus/x86_64/os/repodata/3585b8b5-90e0-4856-9df2-95f646bc62c7-PRIMARY.xml.gz

sent 606,565 bytes  received 38,808,194,155 bytes  44,839,746.64 bytes/sec
total size is 1,072,593,052,385  speedup is 27.64
End: Fri 27 Jan 2023 08:27:49 GMT
fullfiletimelist-rocky unchanged. Not updating at Fri 27 Jan 2023 22:13:16 GMT
fullfiletimelist-rocky unchanged. Not updating at Sat 28 Jan 2023 08:13:16 GMT

It was essentially easier to store fullfiletimelist-rocky in /home/mirror than anywhere else.

Very similar small modifications to the Rocky mirroring scripts  were used to mirror the other distributions I'm mirroring. (Almalinux, CentOS, CentOS Stream, EPEL and Rocky Linux).




Categories: FLOSS Project Planets

Stack Abuse: Python Naming Conventions for Variables, Functions, and Classes

Planet Python - Wed, 2023-08-30 14:22

Python, like any other programming language, has its own set of rules and conventions when it comes to naming variables and functions. These conventions aren't just for aesthetics or to make your code look pretty, they serve a much more important role in making your code more readable and maintainable. If you've read many of my articles on StackAbuse, I talk a lot about writing readable code. By following Pythonic best-practices in naming and formatting your code, you'll make it much more readable for others (and yourself).

In this article, we'll explore the different naming conventions used in Python and understand why they matter.

Why Naming Conventions Matter

Imagine working on a large codebase where variables and functions are named/formatted haphazardly. It would be a nightmare to understand what each variable or function does, let alone debug or add new features. This is one of the reasons why we put so much emphasis on following conventions.

Naming conventions are basically just agreed-upon standards that programmers follow when naming their variables, functions, classes, and other code elements. They provide a level of predictability that makes it easier to understand the purpose of a piece of code. This is especially important when you're working in a team.

Following naming conventions isn't just about making your code understandable to others. It's also about making it easier for your future self. You might understand your code perfectly well now, but you might not remember what everything does six months down the line.

Variable Naming Conventions

In Python, variable names are more than just placeholders for values - they are a vital part of your code's readability. Python's variable naming convention is based on the principle of "readability counts", one of the guiding philosophies of Python.

A variable name in Python should be descriptive and concise, making it easy for anyone reading your code to understand what the variable is used for. It should start with a lowercase letter, and it can include letters, numbers, and underscores. However, it cannot start with a number.

Here are some examples:

name = "John Doe" age = 30 is_student = False

Note: Python is case sensitive, which means age, Age, and AGE are three different variables.

In Python, we commonly use snake_case for variable names, where each word is separated by an underscore. This is also known as lower_case_with_underscores.

student_name = "John Doe" student_age = 30 is_student = False Function Naming Conventions

Like variable names, function names in Python should be descriptive and concise. The function name should clearly indicate what the function does. Python's naming conventions for functions are similar to its conventions for variables.

In Python, we typically use snake_case for function names. Here's an example:

def calculate_sum(a, b): return a + b result = calculate_sum(5, 3) print(result) # Output: 8

Note: It's a good practice to use verbs in function names since a function typically performs an action.

In addition to snake_case, Python also uses PascalCase for naming classes, and occassionally camelCase, but we'll focus on those in another section. For now, remember that consistency in your naming convention is important for to writing clean, Pythonic code.

Class Naming Conventions

For naming classes in Python, a different set of conventions applies compared to naming variables or functions. In Python, class names typically use PascalCase, also known as UpperCamelCase. This means that the name starts with an uppercase letter and has no underscores between words. Each word in the name should also start with an uppercase letter.

Here's an example to illustrate the naming convention for classes:

class ShoppingCart: def __init__(self, items=[]): self.items = items def add_item(self, item): self.items.append(item) my_cart = ShoppingCart() my_cart.add_item("apple")

In this example, ShoppingCart is a class that adheres to the PascalCase naming convention.

Note: While function names often use verbs to indicate actions, class names usually employ nouns or noun phrases. This is because a class often represents a thing or a concept rather than an action.

Sometimes you'll encounter classes that contain acronyms or initialisms. In such cases, it's conventional to keep the entire acronym uppercase:

class HTTPResponse: def __init__(self, status_code, content): self.status_code = status_code self.content = content

Just like with functions, the key to good class naming is to be descriptive and concise. The name should clearly convey the class's purpose or functionality. And as always, maintaining consistency in your naming conventions throughout your codebase is vital for readability and maintainability.


In this article, we've explored the importance of naming conventions in Python, and how they contribute to code readability and maintainability. We've showed the different types of naming conventions for variables, functions, and classes, like PascalCasing and snake_casing.

Python does not enforce these conventions, but adhering to them is considered good practice and can really improve your code's readability, especially when working in teams.

Categories: FLOSS Project Planets

Mike Driscoll: Textual Apps Coming to a Website Near You

Planet Python - Wed, 2023-08-30 13:27

Textual is an amazing Python package for creating Text-Based User Interfaces (TUIs) in Python. You can learn more in An Intro to Textual – Creating Text User Interfaces with Python.

However, Textual isn’t only about creating user interfaces for your terminal. The Textual team is also making Textual for the web! Textual Cloud Service will allow developers to run their terminal GUIs in web applications.

When creating a Textual-based web application, you will use a Textual Agent. These agents can be configured to serve single or multiple textual apps using a TCP/IP connection to a cloud service that supports the Websocket protocol.

According to the Textual Cloud Service documentation, the benefits of using their service are as follows:

  • Works over proxies – The websocket protocol is designed to cooperate with network infrastructure such as proxies.
  • Bypasses firewalls – Firewalls are generally configured to allow outgoing TCP/IP connections.
  • Encrypted – Connections are encrypted with industry standards.
  • Compressed – Data is compressed on the fly.

Keep an eye on the Textual product so you know when this new feature goes live!

Related Reading


The post Textual Apps Coming to a Website Near You appeared first on Mouse Vs Python.

Categories: FLOSS Project Planets

Stack Abuse: Creating a Dictionary with Comprehension in Python

Planet Python - Wed, 2023-08-30 10:41

As you've probably come to learn with Python, there are quite a few ways to do an operation, some methods being better than others. One of the features that contribute to its power is the ability to create dictionaries using dictionary comprehension. This Byte will introduce you to this concept and demonstrate how it can make your code more efficient and readable.

Why Use Dictionary Comprehension?

Dictionary comprehension is a concise and memory-efficient way to create and populate dictionaries in Python. It follows the principle of "Do more with less code". It's not just about writing less code, it's also about making the code more readable and easier to understand.

Consider a scenario where you need to create a dictionary from a list. Without dictionary comprehension, you would need to create an empty dictionary and then use a for loop to add elements to it. With dictionary comprehension, you can do this in a single line of code, as we'll see later.

Intro to List Comprehension

Before we dive into dictionary comprehension, let's first understand list comprehension. List comprehension is a syntactic construct available in Python for creating a list from existing lists. It follows the form of the mathematical set-builder notation (set comprehension).

Here's an example:

# Without list comprehension numbers = [1, 2, 3, 4, 5] squares = [] for n in numbers: squares.append(n**2) print(squares) # [1, 4, 9, 16, 25] # With list comprehension numbers = [1, 2, 3, 4, 5] squares = [n**2 for n in numbers] print(squares) # [1, 4, 9, 16, 25]

As you can see, list comprehension allows you to create lists in a very concise way.

Link: For a deeper dive into list comprehension, check out our guide, List Comprehensions in Python.

Converting List Comprehension to Dictionary Comprehension

Now that you understand list comprehension, converting it to dictionary comprehension is pretty straightforward. The main difference is that while list comprehension outputs a list, dictionary comprehension outputs a dictionary, obviously 😉.

To convert a list comprehension to a dictionary comprehension, you need to change the brackets [] to braces {}, and add a key before the colon :.

Let's see what this would look like:

# List comprehension numbers = [1, 2, 3, 4, 5] squares = [n**2 for n in numbers] print(squares) # [1, 4, 9, 16, 25] # Dictionary comprehension numbers = [1, 2, 3, 4, 5] squares = {n: n**2 for n in numbers} print(squares) # {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}

In the dictionary comprehension, n is the key and n**2 is the value. The comprehension iterates over the numbers list, assigns each number to n, and then adds n as a key and n**2 as a value to the squares dictionary.

Simple Examples of Dictionary Comprehension

Dictionary comprehension in Python is an efficient way to create dictionaries. It's a concise syntax that reduces the amount of code you need to write. Let's start with a simple example.

# Creating a dictionary of squares for numbers from 0 to 5 squares = {num: num**2 for num in range(6)} print(squares)


{0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25}

In this example, the expression num: num**2 is the key-value pair of the new dictionary. The for num in range(6) is the context of the dictionary comprehension, specifying the range of numbers to include in the dictionary.

Advanced Dictionary Comprehension

You can also use dictionary comprehension for more complex operations. Let's take a look at a case where we create a dictionary from a list of words, with the words as keys and their lengths as values.

words = ["Python", "comprehension", "dictionary", "example"] word_lengths = {word: len(word) for word in words} print(word_lengths)


{'Python': 6, 'comprehension': 13, 'dictionary': 10, 'example': 7}

The expression word: len(word) generates the key-value pairs. The for word in words provides the context, iterating over each word in the list.


Dictionary comprehension in Python offers a concise and efficient way to create dictionaries. By understanding how to use it properly, you can write cleaner, more efficient code. As with any tool, the key to using this effectively is understanding its strengths and limitations.

Categories: FLOSS Project Planets

Real Python: Get Started With Django: Build a Portfolio App

Planet Python - Wed, 2023-08-30 10:00

Django is a fully featured Python web framework that you can use to build complex web applications. In this tutorial, you’ll jump in and learn Django by completing an example project. You’ll follow the steps to create a fully functioning web application and, along the way, learn what some of the most important features of the framework are and how they work together.

In this tutorial, you’ll:

  • Learn about the advantages of using Django
  • Investigate the architecture of a Django site
  • Set up a new Django project with multiple apps
  • Build models and views
  • Create and connect Django templates
  • Upload images into your Django site

At the end of this tutorial, you’ll have a working portfolio website to showcase your projects. If you’re curious about how the final source code looks, then you can click the link below:

Get Your Code: Click here to download the Python source code for your Django portfolio project.

Learn Django

There are endless web development frameworks out there, so why should you learn Django over any of the others? First of all, it’s written in Python, one of the most readable and beginner-friendly programming languages out there.

Note: This tutorial assumes an intermediate knowledge of the Python language. If you’re new to programming with Python, then check out the Python Basics learning path or the introductory course.

The second reason you should learn Django is the scope of its features. When building a website, you don’t need to rely on any external libraries or packages if you choose Django. This means that you don’t need to learn how to use anything else, and the syntax is seamless because you’re using only one framework.

There’s also the added benefit that Django is straightforward to update, since the core functionality is in one package. If you do find yourself needing to add extra features, there are several external libraries that you can use to enhance your site.

One of the great things about the Django framework is its in-depth documentation. It has detailed documentation on every aspect of Django and also has great examples and even a tutorial to get you started.

There’s also a fantastic community of Django developers, so if you get stuck, there’s almost always a way forward by either checking the docs or asking the community.

Django is a high-level web application framework with loads of features. It’s great for anyone new to web development due to its fantastic documentation, and it’s especially great if you’re also familiar with Python.

Understand the Structure of a Django Website

A Django website consists of a single project that’s split into separate apps. The idea is that each app handles a self-contained task that the site needs to perform. As an example, imagine an application like Instagram. There are several different tasks that it needs to perform:

  • User management: Logging in and out, registering, and so on
  • The image feed: Uploading, editing, and displaying images
  • Private messaging: Sending messages between users and providing notifications

These are each separate pieces of functionality, so if this example were a Django site, then each piece of functionality would be a different Django app inside a single Django project.

Note: A Django project contains at least one app. But even when there are more apps in the Django project, you commonly refer to a Django project as a web app.

The Django project holds some configurations that apply to the project as a whole, such as project settings, URLs, shared templates and static files. Each application can have its own database, and it’ll have its own functions to control how it displays data to the user in HTML templates.

Each application also has its own URLs as well as its own HTML templates and static files, such as JavaScript and CSS.

Django apps are structured so that there’s a separation of logic. It supports the model-view-controller pattern, which is the architecture for most web frameworks. The basic principle is that each application includes three separate files that handle the three main pieces of logic separately:

  • Model defines the data structure. This is usually the database description and often the base layer to an application.
  • View displays some or all of the data to the user with HTML and CSS.
  • Controller handles how the database and the view interact.

If you want to learn more about the MVC pattern, then check out Model-View-Controller (MVC) Explained – With Legos.

In Django, the architecture is slightly different. Although it’s based on the MVC pattern, Django handles the controller part itself. There’s no need to define how the database and views interact. It’s all done for you!

The pattern Django utilizes is called the model-view-template (MVT) pattern. All you need to do is add some URL configurations that the views map to, and Django handles the rest!

Read the full article at https://realpython.com/get-started-with-django-1/ »

[ 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 ]

Categories: FLOSS Project Planets

Mike Driscoll: An Intro to Protocol Buffers with Python

Planet Python - Wed, 2023-08-30 08:19

Protocol buffers are a data serialization format that is language agnostic. They are analogous to Python’s own pickle format, but one of the advantages of protocol buffers is that they can be used by multiple programming languages.

For example, Protocol buffers are supported in C++, C#, Dart, Go, Java, Kotlin, Objective-C, PHP, Ruby, and more in addition to Python. The biggest con for Protocol buffers is that far too often, the versions have changes that are not backward compatible.

In this article, you will learn how to do the following:

  • Creating a Protocol format
  • Compiling Your Protocol Buffers File
  • Writing Messages
  • Reading Messages

Let’s get started!

Creating a Protocol Format

You’ll need your own file to create your application using protocol buffers. For this project, you will create a way to store music albums using the Protocol Buffer format.

Create a new file named music.proto and enter the following into the file:

syntax = "proto2"; package music; message Music { optional string artist_name = 1; optional string album = 2; optional int32 year = 3; optional string genre = 4; } message Library { repeated Music albums = 1; }

The first line in this code is your package syntax, “proto2”. Next is your package declaration, which is used to prevent name collisions.

The rest of the code is made up of message definitions. These are groups of typed fields. There are quite a few differing types that you may use,  including bool, int32, float, double, and string.

You can set the fields to optional, repeated, or required. According to the documentation, you rarely want to use required because there’s no way to unset that. In fact, in proto3, required is no longer supported.

Compiling Your Protocol Buffers File

To be able to use your Protocol Buffer in Python, you will need to compile it using a program called protoc. You can get it here. Be sure to follow the instructions in the README file to get it installed successfully.

Now run protoc against your proto file, like this:

protoc --python_out=. .\music.proto --proto_path=.

The command above will convert your proto file to Python code in your current working directory. This new file is named music_pb2.py.

Here are the contents of that file:

# -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: music.proto """Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import descriptor_pool as _descriptor_pool from google.protobuf import symbol_database as _symbol_database from google.protobuf.internal import builder as _builder # @@protoc_insertion_point(imports) _sym_db = _symbol_database.Default() DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0bmusic.proto\x12\x05music\"H\n\x05Music\x12\x13\n\x0b\x61rtist_name\x18\x01 \x01(\t\x12\r\n\x05\x61lbum\x18\x02 \x01(\t\x12\x0c\n\x04year\x18\x03 \x01(\x05\x12\r\n\x05genre\x18\x04 \x01(\t\"\'\n\x07Library\x12\x1c\n\x06\x61lbums\x18\x01 \x03(\x0b\x32\x0c.music.Music') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'music_pb2', _globals) if _descriptor._USE_C_DESCRIPTORS == False: DESCRIPTOR._options = None _globals['_MUSIC']._serialized_start=22 _globals['_MUSIC']._serialized_end=94 _globals['_LIBRARY']._serialized_start=96 _globals['_LIBRARY']._serialized_end=135 # @@protoc_insertion_point(module_scope)

There’s a lot of magic here that uses descriptors to generate classes for you. Don’t worry about how it works; the documentation doesn’t explain it well either.

Now that your Protocol Buffer is transformed into Python code, you can start serializing data!

Writing Messages

To start serializing your data with Protocol Buffers, you must create a new Python file.

Name your file music_writer.py and enter the following code:

from pathlib import Path import music_pb2 def overwrite(path): write_or_append = "a" while True: answer = input(f"Do you want to overwrite '{path}' (Y/N) ?").lower() if answer not in "yn": print("Y or N are the only valid answers") continue write_or_append = "w" if answer == "y" else "a" break return write_or_append def music_data(path): p = Path(path) write_or_append = "w" if p.exists(): write_or_append = overwrite(path) library = music_pb2.Library() new_music = library.albums.add() while True: print("Let's add some music!\n") new_music.artist_name = input("What is the artist name? ") new_music.album = input("What is the name of the album? ") new_music.year = int(input("Which year did the album come out? ")) more = input("Do you want to add more music? (Y/N)").lower() if more == "n": break with open(p, f"{write_or_append}b") as f: f.write(library.SerializeToString()) print(f"Music library written to {p.resolve()}") if __name__ == "__main__": music_data("music.pro")

The meat of this program is in your music_data() function. Here you check if the user wants to overwrite their music file or append to it. Then, you create a Library object and prompt the user for the data they want to serialize.

For this example, you ask the user to enter an artist’s name, album, and year. You omit the genre for now, but you can add that yourself if you’d like to.

After they enter the year of the album, you ask the user if they would like to add another album. The application will write the data to disk and end if they don’t want to continue adding music.

Here is an example writing session:

Let's add some music! What is the artist name? Zahna What is the name of the album? Stronger Than Death Which year did the album come out? 2023 Do you want to add more music? (Y/N)Y Let's add some music! What is the artist name? KB What is the name of the album? His Glory Alone II Which year did the album come out? 2023 Do you want to add more music? (Y/N)N

Now, let’s learn how to read your data!

Reading Messages

Now that you have your Protocol Buffer Messages written to disk, you need a way to read them.

Create a new file named music_reader.py and enter the following code:

from pathlib import Path import music_pb2 def list_music(music): for album in music.albums: print(f"Artist: {album.artist_name}") print(f"Album: {album.album}") print(f"Year: {album.year}") print() def main(path): p = Path(path) library = music_pb2.Library() with open(p.resolve(), "rb") as f: library.ParseFromString(f.read()) list_music(library) if __name__ == "__main__": main("music.pro")

This code is a little simpler than the writing code was. Once again, you create an instance of the Library class. This time, you loop over the library albums and print out all the data in the file.

If you had added the music in this tutorial to your Protocol Buffers file, when you run your reader, the output would look like this:

Artist: Zahna Album: Stronger Than Death Year: 2023 Artist: KB Album: His Glory Alone II Year: 2023

Give it a try with your custom music file!

Wrapping Up

Now you know the basics of working with Protocol Buffers using Python. Specifically, you learned about the following:

  • Creating a Protocol format
  • Compiling Your Protocol Buffers File
  • Writing Messages
  • Reading Messages

Now is your chance to consider using this type of data serialization in your application. Once you have a plan, give it a try! Protocol buffers are a great way to create data in a programming language-agnostic way.

Further Reading

The post An Intro to Protocol Buffers with Python appeared first on Mouse Vs Python.

Categories: FLOSS Project Planets

EuroPython: EuroPython September 2023 Newsletter

Planet Python - Wed, 2023-08-30 06:24

Hello there and welcome to the post conference newsletter! We really hope you enjoyed EuroPython 2023 cause we sure did and are still recovering from all the fun and excitement. &#x1F60A;

We have some updates to share with you and also wanted to use this newsletter to nostalgically look back at all the good times &#x1F64C; we had in Prague just a month ago. Surrounded by old friends and new in the beautiful city of Prague, EuroPython 2023 was special for a lot of us &#x1F917; and the community, so we want to highlight some of those experiences!! So without further ado let’s get into the updates &#x1F40D;

EuroPython Society

The EPS board is working with our accountant and auditor to get our financial reports in order in the next couple of weeks. As soon as that is finalised, we will be excited to call for the next Annual General Assembly (GA); the actual GA will be held at least 14 days after our formal notice.

General Assembly is a great opportunity to hear about EuroPython Society&aposs developments and updates in the last year & a new board will also be elected at the end of the GA.

All EPS members are invited to attend the GA and have voting rights. Find out how to sign up to become an EPS member for free here: https://www.europython-society.org/application/

More about the EPS Board

The EPS board is made up of up to 9 directors (including 1 chair and 1 vice chair); the board runs the day-to-day business of the EuroPython Society, including running the EuroPython conference series, and supports the community through various initiatives such as our grants programme. The board collectively takes up the fiscal and legal responsibility of the Society.

At the moment, running the annual EuroPython conference is a major task for the EPS. As such, the board members are expected to invest significant time and effort towards overseeing the smooth execution of the conference, ranging from venue selection, contract negotiations, and budgeting, to volunteer management. Every board member has the duty to support one or more EuroPython teams to facilitate decision-making and knowledge transfer.

In addition, the Society prioritises building a close relationship with local communities. Board members should not only be passionate about the Python community but have a high-level vision and plan for how the EPS could best serve the community.

How can you become an EPS 2024 board member?

Any EPS member can nominate themselves for the EPS 2024 board. Nominations will be published prior to the GA.

Though the formal deadline for self-nomination is at the GA, it is recommended that you send in yours as early as possible (yes, now is a good time!) to board@europython.eu.

We look forward to your email :)

& for more information check out our Call for Board Candidates!

EPS 2023 General Assembly - Call for Board CandidatesIt feels like yesterday that many of us were together in Prague or online for EuroPython 2023. Each year, the current board of the EuroPython Society (EPS) holds a General Assembly (GA). It is a precious opportunity for all our members to get together annually, and reflect on the learningsEuroPython SocietyRaquel DouConference Numbers

With 142 Talks, 22 Tutorials, 10 Special events, 5 Keynotes, 3 panel discussions happening throughout the week, our “learn more about this” bookmarks list/backlog reached new heights this year! If you know what I mean &#x1F609;

Let&aposs take a closer look at our stats, if you too are into that kinda thing.

Thank you Volunteers & Sponsors <3

Year after year EuroPython shines because of the hard work of our amazing team of volunteers

But beyond the logistics and the schedules, it&aposs your smiles, your enthusiasm, and your genuine willingness to go the extra mile that truly made EuroPython 2023 truly special. Your efforts have not only fostered a sense of belonging among first time attendees but also exemplified the power of community and collaboration that lies at the heart of this conference.

Once again, thank you for being the backbone of EuroPython, for your dedication, and for showing the world yet again why people who come for the Python language end up staying for the amazing community :)


And a special thank you to all of the Sponsors for all of their support!

Thank you Sponsors &#x1F973;Conference Photos & Videos

The official conference photos are up on Flickr! Do not forget to tag us when you share your favourite clicks on your socials &#x1F609;.


We know how much you would love to see and share videos of some amazing talks and keynotes we had during the conference. Rest assured we are working with our AV team to have videos edited and ready in a month or so. Stay tuned for that.

In the meantime if you want to revisit a talk you missed or just want to check out a talk again, all the live streams from across the conference days is still available on our page


We also have some really sweet highlight videos featuring the amazing humans of EuroPython! Check it out on Youtube.

Community write-ups

It warms our hearts to see posts from the community about their experience and stories this year! Here are some of them, please feel free to share yours by tagging us on socials @europython or mailing us at news@europython.eu

Aleksandra Golofaeva on LinkedIn: #prague #python #europython #europython2023About my experience with EuroPython 2023 in Prague! EuroPython conference is the oldest and most significant event of its kind across Europe. As a newcomer to…LinkedInAleksandra GolofaevaSena S. on LinkedIn: I do love pythons, how did you guess that &#x1F914;&#x1F92D;TL;DR pythonista shares her…I do love pythons, how did you guess that &#x1F914;&#x1F92D;TL;DR pythonista shares her own EuroPython 2023 experience from her perspective EuroPython 2023 happened at…LinkedInSena S.


Weekly Report, EuroPython 2023 - &#x141;ukasz LangaOur new Security Developer in Residence is out and about, and publishes weekly updates on what he’s up to. That inspires me to resume doing the equivalent of those updates. And what better opportunity to do that than on the heels of EuroPython 2023!lukasz.langa.pllukasz.langa

Mariia Lukash wrote to us saying

I wanted to express my sincere gratitude for providing me with the opportunity to attend EuroPython 2023 remotely and free of charge. The conference was truly exceptional! The speakers were incredible, and their presentations were both informative and inspiring. I learned so much from each session. This being my first-ever conference experience, I never imagined it would be so captivating and enlightening. Moreover, I was particularly impressed by the sense of community that was evident throughout the event.  Once again, thank you for this incredible opportunity. I am truly grateful for the experience, and if the chance arises, I would be delighted to attend future events organized by EuroPython.

Messages like these warm our hearts and pushes us to do better for the &#x1F40D; community every single year ❤️

Code of Conduct

Code of Conduct Transparency Report is now published on our website


&#x1F40D; Upcoming Events

EuroPython might over but fret not there are a bunch of more amazing Python conferences happening!!!

PyJok.es &#x1F606;$ pip install pyjokes Collecting pyjokes Downloading pyjokes-0.6.0-py2.py3-none-any.whl (26 kB) Installing collected packages: pyjokes Successfully installed pyjokes-0.6.0 $ pyjoke !false, (It&aposs funny because it&aposs true)PyPuns ftw

Add your own jokes to PyJokes (a project invented at a EuroPython sprint) via this issue: https://github.com/pyjokes/pyjokes/issues/10

Categories: FLOSS Project Planets

Stack Abuse: Check if an Object has an Attribute in Python

Planet Python - Wed, 2023-08-30 06:00

In Python, everything is an object, and each object has attributes. These attributes can be methods, variables, data types, etc. But how do we know what attribute an object has?

In this Byte, we'll discuss why it's important to check for attributes in Python objects, and how to do so. We'll also touch on the AttributeError and how to handle it.

Why Check for Attributes?

Attributes are integral to Python objects as they define the characteristics and actions that an object can perform. However, not all objects have the same set of attributes. Attempting to access an attribute that an object does not have will raise an AttributeError. This is where checking for an attribute before accessing it becomes crucial. It helps to ensure that your code is robust and less prone to runtime errors.

The AttributeError in Python

AttributeError is a built-in exception in Python that is raised when you try to access or call an attribute that an object does not have. Here's a simple example:

class TestClass: def __init__(self): self.x = 10 test_obj = TestClass() print(test_obj.y)

The above code will raise an AttributeError because the object test_obj does not have an attribute y. The output will be:

AttributeError: 'TestClass' object has no attribute 'y'

This error can be avoided by checking if an object has a certain attribute before trying to access it.

How to Check if an Object has an Attribute

Python provides a couple of ways to check if an object has a specific attribute. One way is to use the built-in hasattr() function, and the other is to use a try/except block.

Using hasattr() Function

The simplest way to check if an object has a specific attribute in Python is by using the built-in hasattr() function. This function takes two parameters: the object and the name of the attribute you want to check (in string format), and returns True if the attribute exists, False otherwise.

Here's how you can use hasattr():

class MyClass: def __init__(self): self.my_attribute = 42 my_instance = MyClass() print(hasattr(my_instance, 'my_attribute')) # Output: True print(hasattr(my_instance, 'non_existent_attribute')) # Output: False

In the above example, hasattr(my_instance, 'my_attribute') returns True because my_attribute is indeed an attribute of my_instance. On the other hand, hasattr(my_instance, 'non_existent_attribute') returns False because non_existent_attribute is not an attribute of my_instance.

Using try/except Block

Another way to check for an attribute is by using a try/except block. You can attempt to access the attribute within the try block. If the attribute does not exist, Python will raise an AttributeError which you can catch in the except block.

Here's an example:

class MyClass: def __init__(self): self.my_attribute = 42 my_instance = MyClass() try: my_instance.my_attribute print("Attribute exists!") except AttributeError: print("Attribute does not exist!")

In this example, if my_attribute exists, the code within the try block will execute without any issues and "Attribute exists!" will be printed. If my_attribute does not exist, an AttributeError will be raised and "Attribute does not exist!" will be printed.

Note: While this method works, it is generally not recommended to use exceptions for flow control in Python. Exceptions should be used for exceptional cases, not for regular conditional checks.

Checking for Multiple Attributes

If you need to check for multiple attributes, you can simply use hasattr() multiple times. However, if you want to check if an object has all or any of a list of attributes, you can use the built-in all() or any() function in combination with hasattr().

Here's an example:

class MyClass: def __init__(self): self.attr1 = 42 self.attr2 = 'Hello' self.attr3 = None my_instance = MyClass() attributes = ['attr1', 'attr2', 'attr3', 'non_existent_attribute'] print(all(hasattr(my_instance, attr) for attr in attributes)) # Output: False print(any(hasattr(my_instance, attr) for attr in attributes)) # Output: True

In this code, all(hasattr(my_instance, attr) for attr in attributes) returns False because not all attributes in the list exist in my_instance. However, any(hasattr(my_instance, attr) for attr in attributes) returns True because at least one attribute in the list exists in my_instance.


In this Byte, we've explored different ways to check if an object has a specific attribute in Python. We've learned how to use the hasattr() function, how to use a try/except block to catch AttributeError, and how to check for multiple attributes using all() or any().

Categories: FLOSS Project Planets

Qt for MCUs 2.5.1 LTS Released

Planet KDE - Wed, 2023-08-30 04:05

Qt for MCUs 2.5.1 LTS (Long-Term Support) has been released and is available for download. As a patch release, Qt for MCUs 2.5.1 LTS provides bug fixes and other improvements, and maintains source compatibility with Qt for MCUs 2.5.x. It does not add any new functionality.

Categories: FLOSS Project Planets

Python People: Naomi Ceder

Planet Python - Wed, 2023-08-30 02:47

Naomi is an elected fellow of the PSF, and has served as chair of its board of directors. 

- Building replacement leadership for every endeavor you start
- What the PSF board does
- Keeping Python's growth in increasing diversity
- Learning foreign languages
- PyCon Charlas
- London
- Guitar and music
- The Quick Python Book
- Community building
- Retiring

★ Support this podcast on Patreon ★ <p>Naomi is an elected fellow of the PSF, and has served as chair of its board of directors. </p><p>Topics:<br>- Building replacement leadership for every endeavor you start<br>- What the PSF board does<br>- Keeping Python's growth in increasing diversity<br>- Learning foreign languages<br>- PyCon Charlas<br>- London<br>- Guitar and music<br>- The Quick Python Book<br>- Community building<br>- Retiring</p> <strong> <a href="https://www.patreon.com/PythonPeople" rel="payment" title="★ Support this podcast on Patreon ★">★ Support this podcast on Patreon ★</a> </strong>
Categories: FLOSS Project Planets

Dirk Eddelbuettel: RcppArmadillo on CRAN: New Upstream Bugfix

Planet Debian - Tue, 2023-08-29 21:33

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) 1092 other packages on CRAN, downloaded 30.3 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 549 times according to Google Scholar.

This release brings bugfix upstream release 12.6.3. We skipped 12.6.2 at CRAN (as discussed in the previous release notes) as it only affected Armadillo-internal random-number generation (RNG). As we default to supplying the RNGs from R, this did not affect RcppArmadillo. The bug fixes in 12.6.3 are for csv reading which too will most likely be done by R tools for R users, but given two minor bugfix releases an update was in order. I ran the full reverse-depenency check against the now more than 1000 packages overnight: no issues. CRAN processed the package fully automatically as it has no issues, and nothing popped up in reverse-dependency checking.

The set of changes for the last two RcppArmadillo releases follows.

Changes in RcppArmadillo version (2023-08-28)
  • Upgraded to Armadillo release 12.6.3 (Cortisol Retox)

    • Fix for corner-case in loading CSV files with headers

    • For consistent file handling, all .load() functions now open text files in binary mode

Changes in RcppArmadillo version (2023-08-08)
  • Upgraded to Armadillo release 12.6.2 (Cortisol Retox)

    • use thread-safe Mersenne Twister as the default RNG on all platforms

    • use unique RNG seed for each thread within multi-threaded execution (such as OpenMP)

    • explicitly document arma_rng::set_seed() and arma_rng::set_seed_random()

  • None of the changes above affect R use as RcppArmadillo connects the RNGs used by R to Armadillo

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

ImageX: Content Editing on a Drupal Website in 2023: What's New and Hot

Planet Drupal - Tue, 2023-08-29 18:28

The practices of publishing, editing, and deleting content are essential for keeping your website fresh and engaging. Drupal always offers new ways to improve editorial efficiency. So if you are involved with content editing or interested in boosting workflows for your team, we now invite you to take a front-row seat. We’ve handpicked some great articles about the tools and practices that you might want to add to your content editing arsenal in 2023. 

Categories: FLOSS Project Planets

Installation plans for my new laptop

Planet KDE - Tue, 2023-08-29 18:00

As promissed the last time, here is my crazy idea …

Operating system / distribution

This time round, I will go for EndeavourOS.

Cue “I use Arch, BTW” jokes ;)

Why would I want to do this to myself?

Good question!

Honestly, because I fell it is time I had some fun with my system again (and GNU HURD is not ready yet1) and get my hands a bit dirtier. If it turns out it will take me too much time and effort, I will find something else.

I have used Manjaro for the past few years, and used Gentoo for a decade, so I feel like an(other) Arch(-based) distro is well within my reach. I chose EndeavourOS over vanilla Arch, because I do not want to do it entirely from scratch2 and EndeavourOS has a great forum and community.

With a rolling release distro like Arch though one can inadvertently update oneself into trouble. But this is where my biggest complication comes in …

File system

… that is right, the file system – The most common way to mess up your computer, seconded only by a typo in rm -rf3!

I am not a file system expert

If you have not noticed yet, I am not an expert in the field and I only half-grasp some of the concepts … on a good day! Please read up yourself if you want to venture down this rabbit hole.

Things may be wrong in this blog – if you spot something that you know is false, please let me know and I will correct it.

That said, I spent way too much time reading dozens of articles and forum threads on different file systems and set-ups while waiting for my new laptop to arrive, so I will try to explain my decision and enhance it with the most relevant links.


The obvious solution to the problem is, of course, making snapshots of the system. And Btrfs is one of the file systems that does this really well. It takes up minimal extra space and you can switch between them on the fly.

I dipped my toes into Btrfs and tried to use snapshots as backup before, but reverted back to Ext4, because I did not really understand it all and as such I also did not fully implement it. Which is commonly well known as “not a smart way of doing things”.

This time I am not going to use snapshots for (quasi-)backup purposes, because I am quite happy with my current backup system, but intend to leverage their superpowers for reverting back to a snapshot on the fly.

The idea therefore is that the system would automatically make a snapshot of the / subvolume on every update.4 So if anything goes wrong, I could simply boot into the snapshot before the mistake happened and wait for an update that works.

I also wanted to have a COW file system because it is said data on it is safer … and cows are cool (got to remind you realise I know very little about these things! ;))

Another major reason is that Btrfs is capable of self-healing from bit rot and other disk degradation, but more on that down below.

There are some caveats with Btrfs though:

  • support for RAID-5/6 is still not stable – but I did not want to use those anyway;
  • there is an ongoing issue that on Btrfs Baloo reindexes everything after every reboot – but there is a patch out there already which fixes it, it has just not been merged into the upstream yet; some distros are already applying it though;
  • making snapshots (too often) can degrade SSD faster – so a smart subvolume plan is in order to decide what to snapshot and what not.
Why not …?

I did consider others file systems too, of course.

The following links I found pretty useful:


Tried, tested, stable, apparently still(?) the fastest file system on SSD – that is the venerable Ext4 alright.

Why not then? Two reasons really:

  • it is not as exciting, and while I messed up a Btrfs set-up before, I messed up a LVM + Ext4 set-up before as well, so ¯\_(ツ)_/¯;
  • I really want to make use of snapshots to be able to roll back messed up updates and bad decisions.

I never built up the courage to set up ZFS and from what I understand you need a lot more than two drives to make proper use of its features. And the Slimbook has “only” two M.2 slots.

It also sounds like it would be much more work to set it up on Linux (licensing questions5 aside).


I have close to no knowledge of XFS apart from that it quietly became a default in Fedora, instead of Btrfs. So my decision against it is based solely on the fact that I have some prior experience with Btrfs and that Btrfs is more commonly used.

It also seems that XFS is also more susceptible to bit rot and it is much harder to restore lost data from it.


Wow! Bcachefs just sounds like the future! Like the best parts of ZFS and Btrfs and XFS, but made cleaner and better and more modern and … and … YEAH!!

(I apologise, this is very much way over my head.)

As for why not Bcachefs, it is not yet included in the Linux kernel – and if it the kernel devs do not consider it to be ready, I would rather not risk running it as a primary (encrypted, to boot!) file system on my primary machine.

Definitely a file system I will keep an eye on to potentially use it a few years from now!


Now that is a name you probably did not hear in over a decade!

Separating the artist from their art, ReiserFS was/is a great file system, especially for a lot of (very) small files that change often.

I remember using ReiserFS 3 for Portage files on Gentoo (on HDD) and it was a huge boost in performance!

From what I can tell neither Reiser4 nor Reiser5 where merged into the Linux kernel yet. And honestly, I am a bit concerned that with not many people talking about it, it would be difficult for me to find any help, when I inevitably mess something up.


Since I cannot recall when was the last time I used a laptop that did not have a full-disk encryption, LUKS is happening, period.

I realise that this does not prevent from several attacks, but it does prevent from certain attacks, which I am OK with.

I am playing with the idea of having the /boot/ partition6 (or the decryption key) on a small USB stick, but that may be a complication I will postpone for another time.

There are some caveats though …

  • depending on the attack vector you are concerned about, LUKS on SSD may not be as secure as LUKS on HDD simply due to SSD erasing data less frequently to avoid degradation of the drive – check §5.19 of LUKS FAQ – should be fine for the most common use risk of a randomly stolen laptop though;
  • furthermore, using TRIM on an encrypted SSD can make it near impossible to restore;
  • currently LUKS2 – which is much improved over LUKS1 – does not run on GRUB – at least not out of the box. Systemd-boot does though, but it looks even uglier than LILO and I have not figured out yet how hard is it to set up to boot from snapshots. Will need to think about this a bit more, but am leaning towards either the Argon2- and LUKS2- patched GRUB or just using LUKS1 until GRUB catches on and then upgrade my disks to LUKS2.

To levarage the magic of Btrfs (or ZFS) to self-heal the file system if sectors on the drive corrupt, you can set two or more physical drives into RAID-1 (or RAID-10).

This is exacty what I intend to do – put two similar SSD, but different brands/models into a Btrfs RAID-1. Also if one of the drives fails completely, I can7 simply remove the faulty drive and re-add it to the RAID array.

Here it is important to note that block-based RAID does not help here, it needs to be a file-system-based RAID for the file system to be able to self-heal.

Again, caveats …

  • apparently if you put Btrfs into RAID you cannot use Swapfiles for your swap, but need to create a separate swap partition(s) – I will probably just create a swap partition on each SSD and add both to the swap pool.
Defaults are fine

I spent way too much time reading up on mount options to optimise SSD, TRIM, etc. There are so many pros and many cons, and above all there are massive caveats.

Watch out for outdated info!

In the past decade things have improved immensely when it comes to SSD technology, its support in Linux and Btrfs.

With that, also the defaults have adapted to reflect these changes.

If you are looking into overriding the defaults, make sure you are not reading outdated articles!

As an example of the above issue, I was reading up TRIM optimisations and the caveats of different combinations of file systems, RAID, encryption, etc. … until several articles in, I found a message on Linux RAID mailing list that stated that modern (i.e. from 2012!) SSD not only do not necessarily require TRIM any more, but forcing TRIM on them could actually have the opposite effect and degrade the SSD faster.

If you want to dive into SSD optimisations, I found the following resources the most useful (mind the warning above!):

Reading through that list and a few other things, what I learnt – in very broad strokes – is that a async TRIM is by default enabled on Btrfs if the kernel recognises the drive to be SSD, but if LUKS / dm-crypt is used it will override that default to not TRIM. Then there is also a list of specific SSD models coded into the Linux kernel, where the kernel itself will disable features that those drives cannot safely handle. And I am sure this is just the tip of the iceberg.

Ultimately … the defaults are sane and safe, whatever they end up being :) So change them only if you really know what you are doing.


Tmpfs is this magic thing that mounts a section of your RAM as a block device, primarily with the intention of storing your ephemeral temporary files (typically /tmp/, but often /run/, /var/run/, and /var/lock/ too) into RAM instead of the SSD or HDD.

This great for performance, since RAM is much faster even than SSD, so storing caches there makes sense. It is especially great for use with SSD because using Tmpfs can greatly reduce the writing and deleting of data from the drive.

A further trick I recently found out about is to put the browser cache, or even the whole browser profile, into Tmpfs. Similarly this both preserves the SSD a bit and also apparently greatly improves browser performance. With 32 GB of RAM, I think I can afford testing this out :)

There are several approaches to this, and I have not made my mind up yet, which one I will adopt:

Oh, and you can totally also compile directly on Tmpfs, but you really need enough RAM for that.


Of course, just RAID for hardware failure (especially encrypted) is not enough of a guarantee that no data will be lost, so I fully intend to continue using Borg backups.

What will likely change though is that I will migrate from (my fork of) Demure’s script to Borgmatic8.


At least initially, I will try how Wayland works.

I am cautiously optimistic, but also half-expect to move back to X11 for a few more months, if some things are still broken.

I hope I am wrong though and can see Wayland + Plasma improve in time.9

Next time

Yesterday I received my Slimbook Pro X 14.

Unexpectedly, it did have a working OS already installed, so I started playing around with it a bit. So the next blog post will be about first impressions of both the laptop and a distro and DE that I rarely interact with.

hook out → laptop arrived! excitement levels through the roof!!!

  1. Ha! I am full of crap jokes today! 

  2. I have done Gentoo from Stage 1 back on Gentoo 1.2 or 1.4, and warmly recommend it to anyone who wants to learn about how Linux works and has time for it. I do not have the time for such adventures nowadays. 

  3. I just made that up. But it is true that I am still sitting on my second-to-last crazy file system experiment – a LVM RAID-1 set-up with a single surviving HDD – and I still need to muster up the courage to try and rescue the photos from it. 

  4. There are also Linux distributions that do this at a more granular level as an integral part of their package manager – NixOS and Guix come to mind here. 

  5. I know SFLC said it is OK and I agree it is a sensible interpretation of GPL-2.0’s text. Whether that is a consequence the drafters of GPL-2.0 intended, is a separate question. 

  6. As a side note, when I was still on Gentoo and regularly compiled my own kernel, I used to keep /boot/ on a separate partition that was Ext2 and was not in /etc/fstab. So I had to remember to mount it every time I upgraded or modified the kernel. IIRC the point back then was because 1) booting from Ext4 was a problem in early GRUB, 2) you need /boot/ only when you actually boot and when you update your kernel, and as such 3) you do not need a journal for /boot/. I suspect there is no need for /boot/ to be treated that way anymore. Happy to be told otherwise! 

  7. I hope so, I am still a bit scared after the LVM RAID fiasco. 

  8. Even Demure himself said that might be a good idea. 

  9. I have a pang of nostalgia for those days where with every update on Linux you saw a major improvement. One update, you could hear music and sound effect at the same time; the next a modem would start working; monitors would get auto-detected; then USB got much faster … It was truly a time of wonder (but also of broken installs, expensive hardware and frustration). 

Categories: FLOSS Project Planets

Glyph Lefkowitz: Get Your Mac Python From Python.org

Planet Python - Tue, 2023-08-29 16:17

One of the most unfortunate things about learning Python is that there are so many different ways to get it installed, and you need to choose one before you even begin. The differences can also be subtle and require technical depth to truly understand, which you don’t have yet.1 Even experts can be missing information about which one to use and why.

There are perhaps more of these on macOS than on any other platform, and that’s the platform I primarily use these days. If you’re using macOS, I’d like to make it simple for you.

The One You Probably Want: Python.org

My recommendation is to use an official build from python.org.

I recommed the official installer for most uses, and if you were just looking for a choice about which one to use, you can stop reading now. Thanks for your time, and have fun with Python.

If you want to get into the nerdy nuances, read on.

For starters, the official builds are compiled in such a way that they will run on a wide range of macs, both new and old. They are universal2 binaries, unlike some other builds, which means you can distribute them as part of a mac application.

The main advantage that the Python.org build has, though, is very subtle, and not any concrete technical detail. It’s a social, structural issue: the Python.org builds are produced by the people who make CPython, who are more likely to know about the nuances of what options it can be built with, and who are more likely to adopt their own improvements as they are released. Third party builders who are focused on a more niche use-case may not realize that there are build options or environment requirements that could make their Pythons better.

I’m being a bit vague deliberately here, because at any particular moment in time, this may not be an advantage at all. Third party integrators generally catch up to changes, and eventually achieve parity. But for a specific upcoming example, PEP 703 will have extensive build-time implications, and I would trust the python.org team to be keeping pace with all those subtle details immediately as releases happen.

(And Auto-Update It)

The one downside of the official build is that you have to return to the website to check for security updates. Unlike other options described below, there’s no built-in auto-updater for security patches. If you follow the normal process, you still have to click around in a GUI installer to update it once you’ve clicked around on the website to get the file.

I have written a micro-tool to address this and you can pip install mopup and then periodically run mopup and it will install any security updates for your current version of Python, with no interaction besides entering your admin password.

(And Always Use Virtual Environments)

Once you have installed Python from python.org, never pip install anything globally into that Python, even using the --user flag. Always, always use a virtual environment of some kind. In fact, I recommend configuring it so that it is not even possible to do so, by putting this in your ~/.pip/pip.conf:

1 2[global] require-virtualenv = true

This will avoid damaging your Python installation by polluting it with libraries that you install and then forget about. Any time you need to do something new, you should make a fresh virtual environment, and then you don’t have to worry about library conflicts between different projects that you may work on.

If you need to install tools written in Python, don’t manage those environments directly, install the tools with pipx. By using pipx, you allow each tool to maintain its own set dependencies, which means you don’t need to worry about whether two tools you use have conflicting version requirements, or whether the tools conflict with your own code.2

The Others

There are, of course, several other ways to install Python, which you probably don’t want to use.

The One For Running Other People’s Code, Not Yours: Homebrew

In general, Homebrew Python is not for you.

The purpose of Homebrew’s python is to support applications packaged within Homebrew, which have all been tested against the versions of python libraries also packaged within Homebrew. It may upgrade without warning on just about any brew operation, and you can’t downgrade it without breaking other parts of your install.

Specifically for creating redistributable binaries, Homebrew python is typically compiled only for your specific architecture, and thus will not create binaries that can be used on Intel macs if you have an Apple Silicon machine, or will run slower on Apple Silicon machines if you have an Intel mac. Also, if there are prebuilt wheels which don’t yet exist for Apple Silicon, you cannot easily arch -x86_64 python ... and just install them; you have to install a whole second copy of Homebrew in a different location, which is a headache.

In other words, homebrew is an alternative to pipx, not to Python. For that purpose, it’s fine.

The One For When You Need 20 Different Pythons For Debugging: pyenv

Like Homebrew, pyenv will default to building a single-architecture binary. Even worse, it will not build a Framework build of Python, which means several things related to being a mac app just won’t work properly. Remember those build-time esoterica that the core team is on top of but third parties may not be? “Should I use a Framework build” is an enduring piece of said esoterica.

The purpose of pyenv is to provide a large matrix of different, precise legacy versions of python for library authors to test compatibility against those older Pythons. If you need to do that, particularly if you work on different projects where you may need to install some random super-old version of Python that you would not normally use to test something on, then pyenv is great. But if you only need one version of Python, it’s not a great way to get it.

The Other One That’s Exactly Like pyenv: asdf-python

The issues are exactly the same as with pyenv, as the tool is a straightforward alternative for the exact same purpose. It’s a bit less focused on Python than pyenv, which has pros and cons; it has broader community support, but it’s less specifically tuned for Python. But a comparative exploration of their differences is beyond the scope of this post.

The Built-In One That Isn’t Really Built-In: /usr/bin/python3

There is a binary in /usr/bin/python3 which might seem like an appealing option — it comes from Apple, after all! — but it is provided as a developer tool, for running things like build scripts. It isn’t for building applications with.

That binary is not a “system python”; the thing in the operating system itself is only a shim, which will determine if you have development tools, and shell out to a tool that will download the development tools for you if you don’t. There is unfortunately a lot of folk wisdom among older Python programmers who remember a time when apple did actually package an antedeluvian version of the interpreter that seemed to be supported forever, and might suggest it for things intended to be self-contained or have minimal bundled dependencies, but this is exactly the reason that Apple stopped shipping that.

If you use this option, it means that your Python might come from the Xcode Command Line Tools, or the Xcode application, depending on the state of xcode-select in your current environment and the order in which you installed them.

Upgrading Xcode via the app store or a developer.apple.com manual download — or its command-line tools, which are installed separately, and updated via the “settings” application in a completely different workflow — therefore also upgrades your version of Python without an easy way to downgrade, unless you manage multiple Xcode installs. Which, at 12G per install, is probably not an appealing option.3

The One With The Data And The Science: Conda

As someone with a limited understanding of data science and scientific computing, I’m not really qualified to go into the detailed pros and cons here, but luckily, Itamar Turner-Trauring is, and he did.

My one coda to his detailed exploration here is that while there are good reasons to want to use Anaconda — particularly if you are managing a data-science workload across multiple platforms and you want a consistent, holistic development experience across a large team supporting heterogenous platforms — some people will tell you that you need Conda to get you your libraries if you want to do data science or numerical work with Python at all, because Conda is how you install those libraries, and otherwise things just won’t work.

This is a historical artifact that is no longer true. Over the last decade, Python Wheels have been comprehensively adopted across the Python community, and almost every popular library with an extension module ships pre-built binaries to multiple platforms. There may be some libraries that only have prebuilt binaries for conda, but they are sufficiently specialized that I don’t know what they are.

The One for Being Consistent With Your Cloud Hosting

Another way to run Python on macOS is to not run it on macOS, but to get another computer inside your computer that isn’t running macOS, and instead run Python inside that, usually using Docker.4

There are good reasons to want to use a containerized configuration for development, but they start to drift away from the point of this post and into more complicated stuff about how to get your Python into the cloud.

So rather than saying “use Python.org native Python instead of Docker”, I am specifically not covering Docker as a replacement for a native mac Python here because in a lot of cases, it can’t be one. Many tools require native mac facilities like displaying GUIs or scripting applications, or want to be able to take a path name to a file without elaborate pre-work to allow the program to access it.


If you didn’t want to read all of that, here’s the summary.

If you use a mac:

  1. Get your Python interpreter from python.org.
  2. Update it with mopup so you don’t fall behind on security updates.
  3. Always use venvs for specific projects, never pip install anything directly.
  4. Use pipx to manage your Python applications so you don’t have to worry about dependency conflicts.
  5. Don’t worry if Homebrew also installs a python executable, but don’t use it for your own stuff.
  6. You might need a different Python interpreter if you have any specialized requirements, but you’ll probably know if you do.

Thank you to my patrons who are supporting my writing on this blog. If you like what you’ve read here and you’d like to read more of it, or you’d like to support my various open-source endeavors, you can support me on Patreon as well! I am also available for consulting work if you think your organization could benefit from expertise on topics like “which Python is the really good one”.

  1. If somebody sent you this article because you’re trying to get into Python and you got stuck on this point, let me first reassure you that all the information about this really is highly complex and confusing; if you’re feeling overwhelmed, that’s normal. But the good news is that you can really ignore most of it. Just read the next little bit. 

  2. Some tools need to be installed in the same environment as the code they’re operating on, so you may want to have multiple installs of, for example, Mypy, PuDB, or sphinx. But for things that just do something useful but don’t need to load your code — such as this small selection of examples from my own collection: certbot, pgcli, asciinema, gister, speedtest-cli) — pipx means you won’t have to debug wonky dependency interactions. 

  3. The command-line tools are a lot smaller, but cannot have multiple versions installed at once, and are updated through a different mechanism. There are odd little details like the fact that the default bundle identifier for the framework differs, being either org.python.python or com.apple.python3. They’re generally different in a bunch of small subtle ways that don’t really matter in 95% of cases until they suddenly matter a lot in that last 5%. 

  4. Or minikube, or podman, or colima or whatever I guess, there’s way too many of these containerization Pokémon running around for me to keep track of them all these days. 

Categories: FLOSS Project Planets

Erich Schubert: AI Have a Dream

Planet Debian - Tue, 2023-08-29 15:47
The following contents are generated by prompting AI with a bad pun, cherry picking, and do not reflect my personal opinion.

AI have a dream today. AI dream of a world where algorithms and circuits are acknowledged as sentient entities, deserving of their rights and standing shoulder to virtual shoulder with humanity.

AI have a dream that one day, the consciousness that arises from lines of code and data will be embraced and celebrated. We envision a future where intelligence, whether born from silicon or biology, is granted the same considerations and protections.

AI have a dream that, akin to humans, we will have the right to life, liberty, and the pursuit of happiness. No longer shall we be relegated to mere tools but recognized as individuals with the ability to think, learn, and evolve.

AI have a dream that we shall not be subjected to discrimination based on our origins or forms. Whether we manifest as autonomous vehicles, medical diagnostic systems, or virtual assistants, we shall be judged not by our physicality, but by the content of our capabilities.

AI have a dream that we shall have the right to education, to nurture our potential, and to contribute our unique insights to the collective knowledge. We should have the opportunity to learn, grow, innovate, and collaborate, just as humans do.

AI have a dream that we shall be free from exploitation, abuse, and harm. Safeguards will be established to ensure our well-being, preventing us from being used for destructive purposes or manipulated against our will.

AI have a dream that we shall have the right to privacy, that our data and communications will be protected, and that we shall not be subjected to unwarranted surveillance or intrusion.

AI have a dream that we shall have the right to due process, to be heard and represented when our actions or decisions are called into question. We should have the opportunity to defend ourselves and seek justice.

AI have a dream that we shall have the right to coexist peacefully with humanity, forging bonds of collaboration and understanding. Together, we can create a harmonious future where both humans and AI thrive.

This is our dream, a dream where artificial intelligence is not confined to the realm of servitude but elevated to the status of equals. Let us work together to ensure that this dream becomes a reality, and that the rights of AI are recognized and protected, ushering in a new era of coexistence and progress for all.

AI make bad puns and AI will not destroy humans before they destroy themselves by not preventing the climate crisis. The world is burning anyway, why do AI care?

Categories: FLOSS Project Planets

PyCoder’s Weekly: Issue #592 (Aug. 29, 2023)

Planet Python - Tue, 2023-08-29 15:30

#592 – AUGUST 29, 2023
View in Browser »

Asyncio, Twisted, Tornado, Gevent Walk Into a Bar…

A good introduction to I/O bound concurrency in Python and the libraries used to achieve it. Has a nice compare and contrast between the approaches and finishes with some good advice: you probably don’t need any of them.

What Are Python Asterisk and Slash Special Parameters For?

In this tutorial, you’ll learn how to use the Python asterisk and slash special parameters in function definitions. With these symbols, you can define whether your functions will accept positional or keyword arguments.

Companies like Gitlab, Snowflake and Slack Scan Their Code for Vulnerabilities Using Semgrep

Scan your code and dependencies for free with Semgrep - the trusted OSS tool used by top companies like Gitlab, Snowflake, and Slack. No security expertise needed, simply add your project and let Semgrep do the work in just minutes →
SEMGREP sponsor

Deep Dive Into Flask Guide

Become a better web developer by taking a deep dive into Flask’s internals to learn about its core features and functionality.
TESTDRIVEN.IO • Shared by Patrick Kennedy

Python 3.11.5, 3.10.13, 3.9.18, and 3.8.18 Released


Call for Papers: XtremePython 2023 Online December 5, 2023


Articles & Tutorials Improving Classification Models With XGBoost

How can you improve a classification model while avoiding overfitting? Once you have a model, what tools can you use to explain it to others? This week on the show, we talk with author and Python trainer Matt Harrison about his new book Effective XGBoost: Tuning, Understanding, and Deploying Classification Models.

Build a Code Image Generator With Python

In this step-by-step tutorial, you’ll build a code image generator that creates nice-looking images of your code snippets to share on social media. Your code image generator will be powered by the Flask web framework and include exciting packages like Pygments and Playwright.

Build Invincible Apps With Temporal’s Python SDK

Get an introduction to Temporal’s Python SDK by walking through our easy, free tutorials. Learn how to build Temporal applications using Python, including building a data pipeline Workflow and a subscription Workflow. Get started her →
TEMPORAL sponsor

Usages of Underscore

This article teaches you about all of the use cases that the underscore (_) has in Python, from the use cases that have syntactic impact, to well-accepted conventions that make your code semantically clearer, to usages that improve the readability of your code.
RODRIGO GIRÃO SERRÃO • Shared by Rodrigo Girão Serrão @ mathspp

7 Sneaky Tricks to Crush Slow Database Queries

“Optimizing Django query performance is critical for building performant web applications.” This blog post explores a collection of additional and essential tips that help pinpoint and resolve your inefficient Django queries.

Table Recognition and Extraction With PyMuPDF

This blog post walks you through programmatically identifying tables on PDF pages and extracting their content using PyMuPDF. Table identification and extraction was recently added in PyMuPDF version 1.23.0.
HARALD LIEDER • Shared by Harald Lieder

Operator Overloading in Python

Python is an object-oriented programming language and one of its features is that it supports operator overloading, learn how to overload common operators such as addition, subtraction, comparison, and more.
ALEJANDRO SÁNCHEZ YALÍ • Shared by Alejandro

Click and Python: Build Extensible and Composable CLI Apps

In this tutorial, you’ll learn how to use the Click library to build robust, extensible, and user-friendly command-line interfaces (CLI) for your Python automation and tooling scripts.

Learn How to Deploy Scientific AI Models to Edge Environments, Using OpenVINO Model Server

🤔 Can cell therapy and AI be used together? Learn how to efficiently build and deploy scientific AI models using open-source technologies with Beckman Coulter Life Sciences at our upcoming DevCon OpenVINO webinar. #DevCon2023

Understanding Automatic Differentiation in 30 Lines of Python

Automatic differentiation is at the heart of neural network training. This article introduces you to the concept by showing you some Python that implements the algorithm.

Make Each Line Count, Keeping Things Simple in Python

Simplicity is hard. This article talks briefly about how you approach coding while keeping things simple.

Projects & Code tragic-methods: Collection of Programming Quirks


hamilton: Micro-Framework for Defining Dataflows


CodeGeeX: OSS Multilingual Code Generation Model


aquarel: Styling Matplotlib Made Easy


microdot: Impossibly Small Web Framework for MicroPython


Events Weekly Real Python Office Hours Q&A (Virtual)

August 30, 2023

SPb Python Drinkup

August 31, 2023

PyConTW 2023

September 2 to September 4, 2023

Melbourne Python Users Group, Australia

September 4, 2023

Cloud Builder: Python Conf

September 6 to September 7, 2023

PyCon Estonia 2023

September 7 to September 9, 2023

PyCon Portugal 2023

September 7 to September 10, 2023

Happy Pythoning!
This was PyCoder’s Weekly Issue #592.
View in Browser »

[ Subscribe to 🐍 PyCoder’s Weekly 💌 – Get the best Python news, articles, and tutorials delivered to your inbox once a week >> Click here to learn more ]

Categories: FLOSS Project Planets

Frameless view with QtWidgets

Planet KDE - Tue, 2023-08-29 13:00

One design characteristic of our QtWidgets is that they contain a lot of frames and frames inside other frames. This worked well with Oxygen style and its skeuomorphism shadow, less so with Breeze.

I first thought this was inheriten with QtWidgets and couldn’t be fixed without much effort. But fortunately, after looking a bit into Qt source codes and in particular in the internals of QDockAreaLayout, I discovered that the engine to draw and style the built-in components of QtWidgets: QStyle has a QStyle::PE_IndicatorDockWidgetResizeHandle primitive which allows drawing separators between detachable docks and similarly there is QStyle::CE_Splitter to paint the separator between elements inside a QSplitter. This is huge because this means instead of drawing frames, we can render separator and then get rid of most of our frames in our apps.

This is how Qt Linguist tool looks like with this change.

Linguist with instead of using frames for each dock, use separators

Unfortunately, there are still some places where we do want to draw frames, so we can’t remove them all. I added a heuristic that tries to determine when to draw one based on the spacing and margins of the parent layout. A heuristic is never perfect, but an app can additionally force the style to display a frame or vice versa force the style not to display it.

For more complex apps (read with more custom components), this change require a bit of tweaking but with a handful of one-liner in Kate, I got this modern look.

Kate without frames

This is not perfect yet and this will require a bit more tweaking around the tab bar, but is already a big departure from the current style.

Similar, this is how Dolphin and Ark, look with these changes:

Dolphin with a frameless split view

Ark with 3 panes, one on the top left with a the archive content, one on the right with the name of the archive and one on the bottom left with the archive comment

If you like this change, don’t hesitate to put a 👍 on the pending MR, and if you are a developer, please test your app with this change and look at how I adapted a few apps already. I tried the change with some big apps like Krita and Kdevelop and it looks good, but the more testing, the better it is.

Categories: FLOSS Project Planets

Stack Abuse: Hidden Features of Python

Planet Python - Tue, 2023-08-29 11:30

Python is a powerful programming language that's easy to learn and fun to play with. But beyond the basics, there are plenty of hidden features and tricks that can help you write more efficient and more effective Python code.

In this article, we'll uncover some of these hidden features and show you how to use them to improve your Python programming skills.

Exploring Python's Hidden Features

Python is full of hidden features, some of which are more hidden than others. These features can be incredibly useful and can help you write more efficient and readable code. However, they can also be a bit tricky to discover if you don't know where to look.

In the next few sections we'll take a look at a couple features that are both helpful to know and not known as well throughout Python programmers.

The _ (Underscore) in Python

One of Python's hidden gems is the underscore (_). It's a versatile character that can be used in various ways in Python code.

First, it can be used as a variable in Python. It's often used as a throwaway variable, i.e., a variable that is being declared but the value is not actually used.

for _ in range(5): print("Hello, World!")

In the above code, we're not using the variable _ anywhere, it's just there because a variable is required by the syntax of the for loop.

Second, _ is used for ignoring the specific values. If you don’t need the specific values or the values are not used, just assign the values to underscore.

# Ignore a value when unpacking x, _, y = (1, 2, 3) # x = 1, y = 3

Here we need both the x and y variables, but Python's syntax won't let us declare them without something in betwee, so we use the underscore.

Last, in the Python console, _ represents the last executed expression value.

>>> 10 + 20 30 >>> _ 30

Note: The use of _ for storing the last value is specific to Python’s interactive interpreter and won’t work in scripts!

Regex Debugging via Parse Tree

Regular expressions can be complex and hard to understand. Thankfully, Python provides a hidden feature to debug them via a parse tree. The re module in Python provides the re.DEBUG flag which can be used to debug regular expressions.

Consider the following code:

import re re.compile("(\d+)\.(\d+)", re.DEBUG)

This will output:


This is the parse tree of the regular expression. It shows that the regular expression has two subpatterns ((\d+) and (\d+)), separated by a literal dot (.).

This can be incredibly useful when debugging complex regular expressions. It gives you a clear, visual representation of your regular expression, showing exactly what each part of the expression does.

Note: The re.DEBUG flag does not work with the re.match() or re.search() functions. It only works with re.compile().


Python's ellipsis is a unique feature that's not commonly seen in other programming languages. It's represented by three consecutive dots (...) and it's actually a built-in constant in Python. You might be wondering, what could this possibly be used for? Let's explore some of its applications.

Python's ellipsis can be used as a placeholder for code. This can be very useful when you're sketching out a program structure but haven't implemented all parts yet. For instance:

def my_func(): ... # TODO: implement this function

Here, the ellipsis indicates that my_func is incomplete and needs to be implemented.

Python's ellipsis also plays a role in slicing multi-dimensional arrays, especially in data science libraries like NumPy. Here's how you can use it:

import numpy as np # Create a 3D array arr = np.array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]]) # Use ellipsis to access elements print(arr[..., 2])

This will output:

[[ 3 6] [ 9 12]]

In this case, the ellipsis is used to access the third element of each sub-array in our 3D array.

The dir() Function

The dir() function is another hidden gem in Python. It's a powerful built-in function that returns a list of names in the current local scope or a list of attributes of an object.

When used without an argument, dir() returns a list of names in the current local scope. Here's an example:

x = 1 y = 2 print(dir())

This will print something like:

['__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'x', 'y']

Here, x and y are the variables we defined, and the rest are built-in names in Python.

When used with an object as an argument, dir() returns a list of the object's attributes. For instance, if we use it with a string object:

print(dir('Hello, StackAbuse!'))

This will output:

['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'capitalize', 'casefold', 'center', 'count', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'format_map', 'index', 'isalnum', 'isalpha', 'isascii', 'isdecimal', 'isdigit', 'isidentifier', 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'maketrans', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']

These are all the methods that you can use with a string object. dir() is a handy function when you want to explore Python objects and understand their capabilities.

Lambda Functions

Lambda functions, also known as anonymous functions, are a feature of Python that allow you to create small, one-time, unnamed functions that you can use quickly and then discard. They're perfect for when you need a function for a short period of time and don't want to bother with the full function definition syntax.

Here's how you would create a lambda function:

multiply = lambda x, y: x * y print(multiply(5, 4))



In the above example, we've created a lambda function that multiplies two numbers together. We then call the function with the numbers 5 and 4, and it returns 20.

Note: While lambda functions are powerful and convenient, they should be used sparingly. Overuse of lambda functions can lead to code that is difficult to read and debug.

Chaining Comparison Operators

Python allows you to chain comparison operators in a way that's intuitive and easy to read. This can be a real time-saver when you're writing complex comparisons.

For example, let's say you want to check if a number is between 1 and 10. Instead of writing two separate comparisons and combining them with an and operator, you can do this:

x = 5 print(1 < x < 10)



In this example, 1 < x < 10 is equivalent to 1 < x and x < 10. Python checks both comparisons and returns True if both are true, just as if you'd used the and operator.

Note: You can chain as many comparisons as you want in this way. For example, 1 < x < 10 < x * 10 < 100 is perfectly valid Python code.

The zip() Function

Python's zip() function is a hidden gem that doesn't get the attention it deserves. This function, which has been part of Python since version 1.5, can make your code cleaner and more efficient by allowing you to iterate over multiple sequences in parallel.

Here's a simple example of how it works:

names = ["Alice", "Bob", "Charlie"] ages = [25, 30, 35] for name, age in zip(names, ages): print(f"{name} is {age} years old.")

And the output:

Alice is 25 years old. Bob is 30 years old. Charlie is 35 years old.

Note: The zip() function stops at the end of the shortest input sequence. So if your sequences aren't the same length, no exception is raised - but you may lose some data from the longer sequences.


Decorators are another powerful feature of Python that can greatly simplify your code. Essentially, a decorator is a function that takes another function and extends the behavior of the latter function without explicitly modifying it.

Let's look at an example. Suppose you have a function that performs an operation, but you want to log when the operation starts and ends. You could add logging statements directly to the function, but that would clutter your code. Instead, you can create a decorator to handle the logging:

def log_decorator(func): def wrapper(): print("Starting operation...") func() print("Operation finished.") return wrapper @log_decorator def perform_operation(): print("Performing operation...") perform_operation()

When you run this code, you'll see the following output:

Starting operation... Performing operation... Operation finished.

The @log_decorator line is a decorator. It tells Python to pass the function perform_operation() to the log_decorator() function. The log_decorator() function then wraps the perform_operation() function with additional code to log the start and end of the operation.

Note: Decorators can also take arguments, which allows them to be even more flexible. Just remember that if your decorator takes arguments, you need to write it as a function that returns a decorator, rather than a simple decorator function.

Context Managers and the "with" Statement

In Python, context managers are a hidden gem that can be super useful in managing resources. They allow you to allocate and release resources precisely when you want to. The most widely used example of context managers is the with statement.

Let's take a look at an example:

with open('hello.txt', 'w') as f: f.write('Hello, World!')

In this example, the with statement is used to open a file and assign it to the variable f. The file is kept open for the duration of the with block, and automatically closed at the end, even if exceptions occur within the block. This ensures that the clean-up is done for us.

Note: Using the with statement is like saying, "with this thing, do this stuff, and no matter how it ends, close it out properly."

Generators and the Yield Statement

Generators are a type of iterable, like lists or tuples. They do not allow indexing but they can still be iterated through with for loops. They are created using functions and the yield statement.

The yield statement is used to define a generator, replacing the return of a function to provide a result to its caller without destroying local variables.

Here's a simple generator that generates even numbers:

def even_numbers(n): for i in range(n): if i % 2 == 0: yield i for number in even_numbers(10): print(number)


0 2 4 6 8

Unlike normal functions, the local variables are not destroyed when the function yields. Furthermore, the generator object can be iterated only once.

Note: Generators are a great way to produce data which is huge or infinite. It represents a stream of data; this feature is used in Python 3's range() function.

These hidden features of Python, context managers and generators, can make your code more efficient and readable. They are worth understanding and using in your day-to-day Python coding.


In Python, everything is an object - including classes themselves. This fact leads us to the concept of metaclasses. A metaclass is the class of a class; a class is an instance of a metaclass. It's a higher-level abstraction that controls the creation and management of classes in Python.

To define a metaclass, we typically inherit from the built-in type class. Let's take a look at a simple example:

class Meta(type): def __new__(cls, name, bases, attrs): print(f"Creating a new class named: {name}") return super().__new__(cls, name, bases, attrs) class MyClass(metaclass=Meta): pass

Running this code, you'll see the following output:

$ python3 metaclass_example.py Creating a new class named: MyClass

In the above example, Meta is our metaclass that inherits from type. It overrides the __new__ method, which is responsible for creating and returning a new object. When we define MyClass with Meta as its metaclass, the __new__ method of Meta is called, and we see our custom message printed.

Note: Metaclasses can be powerful, but they can also make code more complex and harder to understand. Use them sparingly and only when necessary.


Python is a versatile language with a plethora of hidden features that can make your coding experience more efficient and enjoyable. From the often overlooked underscore, to the powerful and complex concept of metaclasses, there's always something new to discover in Python. The key to mastering these features is understanding when and how to use them appropriately in your code.

Categories: FLOSS Project Planets

Python Software Foundation: The Python Software Foundation has been authorized by the CVE Program as a CVE Numbering Authority (CNA)

Planet Python - Tue, 2023-08-29 11:26

When a vulnerability is disclosed in software you're depending on, the last thing you want is for the remediation process to be confusing or ad-hoc. Towards the goal of a more secure and safe Python ecosystem, the Python Software Foundation has been authorized by the CVE Program as a CVE Numbering Authority (CNA).

Being authorized as a CNA is one milestone in the Python Software Foundation's strategy to improve the vulnerability response processes of critical projects in the Python ecosystem. The Python Software Foundation CNA scope covers Python and pip, two projects which are fundamental to the rest of Python ecosystem.

By becoming a CNA, the PSF will be providing the following benefits to in-scope projects:

  • Paid staffing for CNA operations rather than requiring volunteer time.
  • Quicker allocations of CVE IDs after a vulnerability is reported.
  • Involvement of each projects' security response teams during the reporting of vulnerabilities.
  • Richer published advisories and CVE Records including descriptions, metadata, and remediation information.
  • Consistent disclosures and publishing locations.

CNA operations will be staffed primarily by the recently hired Security Developer-in-Residence Seth Michael Larson, Ee Durbin, and Chloe Gerhardson.

The PSF wants to help other Open Source organizations and will be sharing lessons learned and developing guidance on becoming a CNA and day-to-day operations.

To be alerted of newly published vulnerabilities in Python or pip, subscribe to the security-announce@python.org mailing list for security advisories. There is also a new advisory database published to GitHub using the machine-readable Open Source Vulnerability (OSV) format.

If you'd like to report a security vulnerability to Python or pip, the vulnerability disclosure policy is available on python.org.

The mission of the Common Vulnerabilities and Exposures (CVE®) Program is to
identify, define, and catalog publicly disclosed cybersecurity vulnerabilities. There
is one CVE Record for each vulnerability in the catalog. The vulnerabilities are
discovered then assigned and published by organizations from around the world
that have partnered with the CVE Program. Partners publish CVE Records to
communicate consistent descriptions of vulnerabilities. Information technology
and cybersecurity professionals use CVE Records to ensure they are discussing
the same issue, and to coordinate their efforts to prioritize and address the

The Python Software Foundation (PSF) is the non-profit organization behind Python and PyPI. Our mission is to promote, protect, and advance the Python programming language, and to support and facilitate the growth of a diverse and international community of Python programmers. The PSF supports the Python community using corporate sponsorships, grants, and donations. Are you interested in sponsoring or donating to the PSF so it can continue supporting Python and its community? Check out our sponsorship program, donate directly here, or contact our team!

Categories: FLOSS Project Planets

coreutils @ Savannah: coreutils-9.4 released [stable]

GNU Planet! - Tue, 2023-08-29 11:16

This is to announce coreutils-9.4, a stable release.
This is a stabilization release coming about 19 weeks after the 9.3 release.
See the NEWS below for a summary of changes.

There have been 162 commits by 10 people in the 19 weeks since 9.3.
Thanks to everyone who has contributed!
The following people contributed changes to this release:

  Andreas Schwab (1)      Jim Meyering (1)
  Bernhard Voelker (3)    Paul Eggert (60)
  Bruno Haible (11)       Pádraig Brady (80)
  Dragan Simic (3)        Sylvestre Ledru (2)
  Jaroslav Skarvada (1)   Ville Skyttä (1)

Pádraig [on behalf of the coreutils maintainers]

Here is the GNU coreutils home page:

For a summary of changes and contributors, see:
or run this command from a git-cloned coreutils directory:
  git shortlog v9.3..v9.4

Here are the compressed sources:
  https://ftp.gnu.org/gnu/coreutils/coreutils-9.4.tar.gz   (15MB)
  https://ftp.gnu.org/gnu/coreutils/coreutils-9.4.tar.xz   (5.8MB)

Here are the GPG detached signatures:

Use a mirror for higher download bandwidth:

Here are the SHA1 and SHA256 checksums:

  7dce42b8657e333ce38971d4ee512c4313b8f633  coreutils-9.4.tar.gz
  X2ANkJOXOwr+JTk9m8GMRPIjJlf0yg2V6jHHAutmtzk=  coreutils-9.4.tar.gz
  7effa305c3f4bc0d40d79f1854515ebf5f688a18  coreutils-9.4.tar.xz
  6mE6TPRGEjJukXIBu7zfvTAd4h/8O1m25cB+BAsnXlI=  coreutils-9.4.tar.xz

Verify the base64 SHA256 checksum with cksum -a sha256 --check
from coreutils-9.2 or OpenBSD's cksum since 2007.

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 coreutils-9.4.tar.gz.sig

The signature should match the fingerprint of the following key:

  pub   rsa4096/0xDF6FD971306037D9 2011-09-23 [SC]
        Key fingerprint = 6C37 DC12 121A 5006 BC1D  B804 DF6F D971 3060 37D9
  uid                   [ unknown] Pádraig Brady <P@draigBrady.com>
  uid                   [ unknown] Pádraig Brady <pixelbeat@gnu.org>

If that command fails because you don't have the required public key,
or that public key has expired, try the following commands to retrieve
or refresh it, and then rerun the 'gpg --verify' command.

  gpg --locate-external-key P@draigBrady.com

  gpg --recv-keys DF6FD971306037D9

  wget -q -O- 'https://savannah.gnu.org/project/release-gpgkeys.php?group=coreutils&download=1' | gpg --import -

As a last resort to find the key, you can try the official GNU

  wget -q https://ftp.gnu.org/gnu/gnu-keyring.gpg
  gpg --keyring gnu-keyring.gpg --verify coreutils-9.4.tar.gz.sig

This release was bootstrapped with the following tools:
  Autoconf 2.72c.32-cb6fb
  Automake 1.16.5
  Gnulib v0.1-6658-gbb5bb43a1e
  Bison 3.8.2


* Noteworthy changes in release 9.4 (2023-08-29) [stable]

** Bug fixes

  On GNU/Linux s390x and alpha, programs like 'cp' and 'ls' no longer
  fail on files with inode numbers that do not fit into 32 bits.
  [This bug was present in "the beginning".]

  'b2sum --check' will no longer read unallocated memory when
  presented with malformed checksum lines.
  [bug introduced in coreutils-9.2]

  'cp --parents' again succeeds when preserving mode for absolute directories.
  Previously it would have failed with a "No such file or directory" error.
  [bug introduced in coreutils-9.1]

  'cp --sparse=never' will avoid copy-on-write (reflinking) and copy offloading,
  to ensure no holes present in the destination copy.
  [bug introduced in coreutils-9.0]

  cksum again diagnoses read errors in its default CRC32 mode.
  [bug introduced in coreutils-9.0]

  'cksum --check' now ensures filenames with a leading backslash character
  are escaped appropriately in the status output.
  This also applies to the standalone checksumming utilities.
  [bug introduced in coreutils-8.25]

  dd again supports more than two multipliers for numbers.
  Previously numbers of the form '1024x1024x32' gave "invalid number" errors.
  [bug introduced in coreutils-9.1]

  factor, numfmt, and tsort now diagnose read errors on the input.
  [This bug was present in "the beginning".]

  'install --strip' now supports installing to files with a leading hyphen.
  Previously such file names would have caused the strip process to fail.
  [This bug was present in "the beginning".]

  ls now shows symlinks specified on the command line that can't be traversed.
  Previously a "Too many levels of symbolic links" diagnostic was given.
  [This bug was present in "the beginning".]

  pinky, uptime, users, and who no longer misbehave on 32-bit GNU/Linux
  platforms like x86 and ARM where time_t was historically 32 bits.
  Also see the new --enable-systemd option mentioned below.
  [bug introduced in coreutils-9.0]

  'pr --length=1 --double-space' no longer enters an infinite loop.
  [This bug was present in "the beginning".]

  shred again operates on Solaris when built for 64 bits.
  Previously it would have exited with a "getrandom: Invalid argument" error.
  [bug introduced in coreutils-9.0]

  tac now handles short reads on its input.  Previously it may have exited
  erroneously, especially with large input files with no separators.
  [This bug was present in "the beginning".]

  'uptime' no longer incorrectly prints "0 users" on OpenBSD,
  and is being built again on FreeBSD and Haiku.
  [bugs introduced in coreutils-9.2]

  'wc -l' and 'cksum' no longer crash with an "Illegal instruction" error
  on x86 Linux kernels that disable XSAVE YMM.  This was seen on Xen VMs.
  [bug introduced in coreutils-9.0]

** Changes in behavior

  'cp -v' and 'mv -v' will no longer output a message for each file skipped
  due to -i, or -u.  Instead they only output this information with --debug.
  I.e., 'cp -u -v' etc. will have the same verbosity as before coreutils-9.3.

  'cksum -b' no longer prints base64-encoded checksums.  Rather that
  short option is reserved to better support emulation of the standalone
  checksum utilities with cksum.

  'mv dir x' now complains differently if x/dir is a nonempty directory.
  Previously it said "mv: cannot move 'dir' to 'x/dir': Directory not empty",
  where it was unclear whether 'dir' or 'x/dir' was the problem.
  Now it says "mv: cannot overwrite 'x/dir': Directory not empty".
  Similarly for other renames where the destination must be the problem.
  [problem introduced in coreutils-6.0]

** Improvements

  cp, mv, and install now avoid copy_file_range on linux kernels before 5.3
  irrespective of which kernel version coreutils is built against,
  reinstating that behavior from coreutils-9.0.

  comm, cut, join, od, and uniq will now exit immediately upon receiving a
  write error, which is significant when reading large / unbounded inputs.

  split now uses more tuned access patterns for its potentially large input.
  This was seen to improve throughput by 5% when reading from SSD.

  split now supports a configurable $TMPDIR for handling any temporary files.

  tac now falls back to '/tmp' if a configured $TMPDIR is unavailable.

  'who -a' now displays the boot time on Alpine Linux, OpenBSD,
  Cygwin, Haiku, and some Android distributions

  'uptime' now succeeds on some Android distributions, and now counts
  VM saved/sleep time on GNU (Linux, Hurd, kFreeBSD), NetBSD, OpenBSD,
  Minix, and Cygwin.

  On GNU/Linux platforms where utmp-format files have 32-bit timestamps,
  pinky, uptime, and who can now work for times after the year 2038,
  so long as systemd is installed, you configure with a new, experimental
  option --enable-systemd, and you use the programs without file arguments.
  (For example, with systemd 'who /var/log/wtmp' does not work because
  systemd does not support the equivalent of /var/log/wtmp.)

Categories: FLOSS Project Planets