skip to navigation
skip to content

Planet Python

Last update: April 07, 2026 04:44 PM UTC

April 07, 2026


Python Engineering at Microsoft

Write SQL Your Way: Dual Parameter Style Benefits in mssql-python

Reviewed by: Sumit Sarabhai If you’ve been writing SQL in Python, you already know the debate: positional parameters (?) or named parameters (%(name)s)? Some developers swear by the conciseness of positional. Others prefer the clarity of named. With mssql-python, you no longer need to choose – we support both.  We’ve added dual parameter style support to mssql-python, enabling both qmark and pyformat parameter styles in Python […]

The post Write SQL Your Way: Dual Parameter Style Benefits in mssql-python appeared first on Microsoft for Python Developers Blog.

April 07, 2026 04:12 PM UTC


Django Weblog

Django security releases issued: 6.0.4, 5.2.13, and 4.2.30

In accordance with our security release policy, the Django team is issuing releases for Django 6.0.4, Django 5.2.13, and Django 4.2.30. These releases address the security issues detailed below. We encourage all users of Django to upgrade as soon as possible.

Django 4.2 has reached the end of extended support

Note that with this release, Django 4.2 has reached the end of extended support. All Django 4.2 users are encouraged to upgrade to Django 5.2 or later to continue receiving fixes for security issues.

See the downloads page for a table of supported versions and the future release schedule.

CVE-2026-3902: ASGI header spoofing via underscore/hyphen conflation

ASGIRequest normalizes header names following WSGI conventions, mapping hyphens to underscores. As a result, even in configurations where reverse proxies carefully strip security-sensitive headers named with hyphens, such a header could be spoofed by supplying a header named with underscores.

Under WSGI, it is the responsibility of the server or proxy to avoid ambiguous mappings. (Django's runserver was patched in CVE-2015-0219.) But under ASGI, there is not the same uniform expectation, even if many proxies protect against this under default configuration (including nginx via underscores_in_headers off;).

Headers containing underscores are now ignored by ASGIRequest, matching the behavior of Daphne, the reference server for ASGI.

This issue has severity "low" according to the Django Security Policy.

Thanks to Tarek Nakkouch for the report.

CVE-2026-4277: Privilege abuse in GenericInlineModelAdmin

Add permissions on inline model instances were not validated on submission of forged POST data in GenericInlineModelAdmin.

This issue has severity "low" according to the Django Security Policy.

Thanks to N05ec@LZU-DSLab for the report.

CVE-2026-4292: Privilege abuse in ModelAdmin.list_editable

Admin changelist forms using ModelAdmin.list_editable incorrectly allowed new instances to be created via forged POST data.

This issue has severity "low" according to the Django Security Policy.

CVE-2026-33033: Potential denial-of-service vulnerability in MultiPartParser via base64-encoded file upload

When using django.http.multipartparser.MultiPartParser, multipart uploads with Content-Transfer-Encoding: base64 that include excessive whitespace may trigger repeated memory copying, potentially degrading performance.

This issue has severity "moderate" according to the Django Security Policy.

Thanks to Seokchan Yoon for the report.

CVE-2026-33034: Potential denial-of-service vulnerability in ASGI requests via memory upload limit bypass

ASGI requests with a missing or understated Content-Length header could bypass the DATA_UPLOAD_MAX_MEMORY_SIZE limit when reading HttpRequest.body, potentially loading an unbounded request body into memory and causing service degradation.

This issue has severity "low" according to the Django Security Policy.

Thanks to Superior for the report.

Affected supported versions

  • Django main
  • Django 6.0
  • Django 5.2
  • Django 4.2

Resolution

Patches to resolve the issue have been applied to Django's main, 6.0, 5.2, and 4.2 branches. The patches may be obtained from the following changesets.

CVE-2026-3902: ASGI header spoofing via underscore/hyphen conflation

CVE-2026-4277: Privilege abuse in GenericInlineModelAdmin

CVE-2026-4292: Privilege abuse in ModelAdmin.list_editable

CVE-2026-33033: Potential denial-of-service vulnerability in MultiPartParser via base64-encoded file upload

CVE-2026-33034: Potential denial-of-service vulnerability in ASGI requests via memory upload limit bypass

The following releases have been issued

The PGP key ID used for this release is Jacob Walls: 131403F4D16D8DC7

General notes regarding security reporting

As always, we ask that potential security issues be reported via private email to security@djangoproject.com, and not via Django's Trac instance, nor via the Django Forum. Please see our security policies for further information.

April 07, 2026 02:00 PM UTC


Real Python

Using Loguru to Simplify Python Logging

Learn how to use Loguru for simpler Python logging, from zero-config setup and custom formats to file rotation, retention, and adding context.

April 07, 2026 02:00 PM UTC


Django Weblog

Could you host DjangoCon Europe 2027? Call for organizers

We are looking for the next group of organizers to own and lead the 2027 DjangoCon Europe conference. Could your town's football stadium, theatre, cinema, city hall, circus tent or a private island host this wonderful community event?

DjangoCon Europe is a major pillar of the Django community, as people from across the world meet and share. Many qualities make it a unique event: Unconventional and conventional venues, creative happenings, a feast of talks and a dedication to inclusion and diversity.

Hosting a DjangoCon is an ambitious undertaking. It's hard work, but each year it has been successfully run by a team of community volunteers, not all of whom have had previous experience - more important is enthusiasm, organizational skills, the ability to plan and manage budgets, time and people - and plenty of time to invest in the project.

For 2027, rest assured that we will be there to answer questions and put you in touch with previous organizers through the brand new DSF Events Support Working Group (a reboot of the previous DjangoCon Europe Support Working Group).

Step 1: Submit your expression of interest

If you're considering organizing DjangoCon Europe (🙌 great!), fill in our DjangoCon Europe 2027 expression of interest form with your contact details. No need to fill in all the information at this stage if you don't have it all already, we'll reach out and help you figure it out.

Express your interest in organizing

Step 2: We're here to help!

We've set up a DjangoCon Europe support working group of previous organizers that you can reach out to with questions about organizing and running a DjangoCon Europe.

The group will be in touch with everyone submitting the expression of interest form, or you can reach out to them directly: events-support@djangoproject.com

We'd love to hear from you as soon as possible, so your proposal can be finalized and sent to the DSF board by June 1st 2026.

Step 3: Submitting the proposal

The more detailed and complete your final proposal is, the better. Basic details include:

We also like to see:

Have a look at our proposed (draft, feedback welcome) DjangoCon Europe 2027 Licensing Agreement for the fine print on contractual requirements and involvement of the Django Software Foundation.

Submit your completed proposal by June 1st 2026 via our DjangoCon Europe 2027 expression of interest form, this time filling in as many fields as possible. We look forward to reviewing great proposals that continue the excellence the whole community associates with DjangoCon Europe.

Q&A

Can I organize a conference alone?

We strongly recommend that a team of people submit an application.

Depending on your jurisdiction, this is usually not a problem. But please share your plans about the entity you will use or form in your application.

Do I/we need experience with organizing conferences?

The support group is here to help you succeed. From experience, we know that many core groups of 2-3 people have been able to run a DjangoCon with guidance from previous organizers and help from volunteers.

What is required in order to announce an event?

Ultimately, a contract with the venue confirming the dates is crucial, since announcing a conference makes people book calendars, holidays, buy transportation and accommodation etc. This, however, would only be relevant after the DSF board has concluded the application process. Naturally, the application itself cannot contain any guarantees, but it's good to check concrete dates with your venues to ensure they are actually open and currently available, before suggesting these dates in the application.

Do we have to do everything ourselves?

No. You will definitely be offered lots of help by the community. Typically, conference organizers will divide responsibilities into different teams, making it possible for more volunteers to join. Local organizers are free to choose which areas they want to invite the community to help out with, and a call will go out through a blog post announcement on djangoproject.com and social media.

What kind of support can we expect from the Django Software Foundation?

The DSF regularly provides grant funding to DjangoCon organizers, to the extent of $6,000 in recent editions. We also offer support via specific working groups:

In addition, a lot of Individual Members of the DSF regularly volunteer at community events. If your team aren't Individual Members, we can reach out to them on your behalf to find volunteers.

What dates are possible in 2027?

For 2027, DjangoCon Europe should happen between January 4th and April 26th, or June 3rd and June 27th. This is to avoid the following community events' provisional dates:

We also want to avoid the following holidays:

What cities or countries are possible?

Any city in Europe. This can be a city or country where DjangoCon Europe has happened in the past (Athens, Vigo, Edinburgh, Porto, Copenhagen, Heidelberg, Florence, Budapest, Cardiff, Toulon, Warsaw, Zurich, Amsterdam, Berlin), or a new locale.

References

Past calls

April 07, 2026 01:06 PM UTC


Real Python

Quiz: Building a Python GUI Application With Tkinter

Test your Tkinter skills with this interactive challenge on widgets, layouts, event loops, and text/file handling in Python GUIs.

April 07, 2026 12:00 PM UTC

Quiz: Using Loguru to Simplify Python Logging

Test your knowledge of Loguru for Python logging, from zero-config setup and log levels to custom formats and adding context.

April 07, 2026 12:00 PM UTC


PyCharm

How to Train Your First TensorFlow Model in PyCharm

This is a guest post from Iulia Feroli, founder of the Back To Engineering community on YouTube. TensorFlow is a powerful open-source framework for building machine learning and deep learning systems. At its core, it works with tensors (a.k.a multi‑dimensional arrays) and provides high‑level libraries (like Keras) that make it easy to transform raw data […]

April 07, 2026 10:36 AM UTC


PyCon

Stories from the PyCon US Hotels

April 07, 2026 10:30 AM UTC

April 06, 2026


ListenData

How to Use Gemini API in Python

April 06, 2026 06:14 PM UTC


PyCon

Python and the Future of AI: Agents, Inference, and Edge AI

April 06, 2026 05:36 PM UTC


Trey Hunner

Using a ~/.pdbrc file to customize the Python Debugger

April 06, 2026 02:30 PM UTC


Real Python

D-Strings Could End Your textwrap.dedent() Days and Other Python News for April 2026

D-strings proposed to kill textwrap.dedent(), Python 3.15 alpha 7 ships lazy imports, GPT-5.4 launches, and Python Insider moves home.

April 06, 2026 02:00 PM UTC

Quiz: For Loops in Python (Definite Iteration)

Test your understanding of Python loops, iterables, and control flow with break, continue, and StopIteration.

April 06, 2026 12:00 PM UTC


Python Bytes

#476 Common themes

Topics include Migrating from mypy to ty: Lessons from FastAPI, Oxyde ORM, Typeshedded CPython docs, and Raw+DC Database Pattern: A Retrospective.

April 06, 2026 08:00 AM UTC

April 05, 2026


EuroPython

Humans of EuroPython: George Zisopoulos

Behind every flawless talk, engaging workshop, and perfectly timed coffee break at EuroPython is a crew of unsung heroes—our volunteers! 🌟 Today we’d like to introduce George Zisopoulos, member of the Operations team at EuroPython 2025.

April 05, 2026 02:18 PM UTC

April 04, 2026


Marcos Dione

Correcting OpenStreetMap wrong tag values

As a hobbyist consumer of OSM data to render maps, I find wrong tags annoying. Bad values mean that the resulting map is wrong or incomplete, so less useful. I decided to attack the most egregious ones, which include typos, street names instead of type and some other errors. The idea is to attack the long tail first, so I'm not blocked because the next batch of errors (objects with exactly the same error) looks too big (yes, OCD).

So I hacked a small python script to help me find and edit them:

#! /usr/bin/env python3

import os

import psycopg2


def main():
    db = psycopg2.connect(dbname='europe')
    cursor = db.cursor()

    cursor.execute('''
        SELECT
            count(*) AS count,
            highway
        FROM planet_osm_line
        WHERE
            highway IS NOT NULL
        GROUP BY highway
        ORDER BY count ASC
    ''')
    data = cursor.fetchall()

    for count, highway in data:
        print(f"next {count}: {highway}")

        cursor.execute('''
            SELECT osm_id
            FROM planet_osm_line
            WHERE
                highway = %s
        ''', (highway, ))

        for (osm_id, ) in cursor.fetchall():
            if osm_id < 0:
                # in rendering DBs, this is a relation
                os.system(f"librewolf -P default 'https://www.openstreetmap.org/edit?relation={-osm_id}'")
            else:
                os.system(f"librewolf -P default 'https://www.openstreetmap.org/edit?way={osm_id}'")


if __name__ == '__main__':
    main()

It is quite inefficient, but what I want is to edit the errors, not to write a script :) This requires a rendering database, which I already have locally :)

From here the workflow is:

In my machine, finding the long tail, and finding each set of errors takes one minute, so I was launching two at the same time. One of the things to notice is that if the object you try to edit does no exists anymore, you get and edit view of the whole planet.

April 04, 2026 10:16 AM UTC


Armin Ronacher

Absurd In Production

April 04, 2026 12:00 AM UTC

April 03, 2026


PyCon

¡Haciendo Historia! Celebrating PyCon US’s First-Ever Spanish-Language Keynote

April 03, 2026 05:20 PM UTC


Real Python

Quiz: How to Add Features to a Python Project With Codex CLI

Test your knowledge of Codex CLI, the AI-powered terminal tool for adding features to Python projects with natural language.

April 03, 2026 12:00 PM UTC

Quiz: Class Concepts: Object-Oriented Programming in Python

Test your understanding of Python classes, attributes, methods, properties, and the descriptor protocol.

April 03, 2026 12:00 PM UTC


Rodrigo Girão Serrão

Indexable iterables

Learn how objects are automatically iterable if you implement integer indexing.

Introduction

An iterable in Python is any object you can traverse through with a for loop. Iterables are typically containers and iterating over the iterable object allows you to access the elements of the container.

This article will show you how you can create your own iterable objects through the implementation of integer indexing.

Indexing with __getitem__

To make an object that can be indexed you need to implement the method __getitem__.

As an example, you'll implement a class ArithmeticSequence that represents an arithmetic sequence, like \(5, 8, 11, 14, 17, 20\). An arithmetic sequence is defined by its first number (\(5\)), the step between numbers (\(3\)), and the total number of elements (\(6\)). The sequence \(5, 8, 11, 14, 17, 20\) is seq = ArithmeticSequence(5, 3, 6) and seq[3] should be \(14\). Using some arithmetic, you can implement indexing in __getitem__ directly:

class ArithmeticSequence:
    def __init__(self, start: int, step: int, total: int) -> None:
        self.start = start
        self.step = step
        self.total = total

    def __getitem__(self, index: int) -> int:
        if not 0 <= index < self.total:
            raise IndexError(f"Invalid index {index}.")

        return self.start + index * self.step

seq = ArithmeticSequence(5, 3, 6)
print(seq[3])  # 14

Turning an indexable object into an iterable

If your object accepts integer indices, then it is automatically an iterable. In fact, you can already iterate over the sequence you created above by simply using it in a for loop:

for value in seq:
    print(value, end=", ")
# 5, 8, 11, 14, 17, 20,

How Python distinguishes iterables from non-iterables

You might ask yourself “how does Python inspect __getitem__ to see it uses numeric indices?” It doesn't! If your object implements __getitem__ and you try to use it as an iterable, Python will try to iterate over it. It either works or it doesn't!

To illustrate this point, you can define a class DictWrapper that wraps a dictionary and implements __getitem__ by just grabbing the corresponding item out of a dictionary:

class DictWrapper:
    def __init__(self, values):
        self.values = values

    def __getitem__(self, index):
        return self.values[index]

Since DictWrapper implements __getitem__, if an instance of DictWrapper just happens to have some integer keys (starting at 0) then you'll be able to iterate partially over the dictionary:

d1 = DictWrapper({0: "hey", 1: "bye", "key": "value"})

for value in d1:
    print(value)
hey
bye
Traceback (most recent call last):
  File "<python-input-25>", line 3, in <module>
    for value in d1:
                 ^^
  File "<python-input-18>", line 6, in __getitem__
    return self.values[index]
           ~~~~~~~~~~~^^^^^^^
KeyError: 2

What's interesting is that you can see explicitly that Python tried to index the object d with the key 2 and it didn't work. In the ArithmeticSequence above, you didn't get an error because you raised IndexError when you reached the end and that's how Python understood the iteration was done. In this case, since you get a KeyError, Python doesn't understand what's going on and just...

April 03, 2026 11:41 AM UTC


Talk Python Blog

Announcing Course Completion Certificates

I’m very excited to share that you can now generate course completion certificates automatically at Talk Python Training. What’s even better is our certificates allow you to one-click add them as official licenses and certifications on LinkedIn.

Remember last week, I added some really nice features to your account page showing which courses are completed and which ones you’ve recently participated in. Just start there. Find a course you recently completed, click certificate, and there is a Share to LinkedIn UI right there. It’s nearly entirely automated.

April 03, 2026 02:39 AM UTC


ListenData

How to Build ChatGPT Clone in Python

April 03, 2026 12:42 AM UTC

How to Use Web Search in ChatGPT API

April 03, 2026 12:38 AM UTC

4 Ways to Use ChatGPT API in Python

April 03, 2026 12:25 AM UTC