Python: use re.prefixmatch() instead of re.match() from Python 3.15
Take this validation function:
(All tags.)
re.prefixmatch() instead of re.match() from Python 3.15Take this validation function:
SyntaxWarning: invalid octal escape sequenceTake this code:
TypeError: NamedTuple() got an unexpected keyword argumentTake this code, defining a small NamedTuple with a keyword argument per field:
New package just landed!
Back in January, I introduced tprof, a targeting profiler for Python 3.12+ that measures the time spent in specific functions, rather than your whole program. As a reminder, here’s the basic usage, specifying a target function with -t and a script to run:
time-machine is my library for mocking the current date and time in Python tests. Its headline advantage over freezegun, the library that inspired it, is speed.
time-machine is my library for mocking the current date and time in Python tests. I’ve just released version 3.3.0 with a decent number of changes, so here’s a lovely summary for you.
ValueError: day of month directive '%d' may not be used without a year directiveTake this code, parsing the date of an annually recurring event that only has a month and day, such as a work anniversary:
TypeError: NotImplemented should not be used in a boolean contextTake this class, which implements __eq__() and derives __ne__() from it:
unittest.mock calls with attached mocksWhen you use a unittest.mock mock, you often make assertions on the calls it received, such as through the mock_calls list. But sometimes you want to assert on the order of calls across multiple mocked functions, for example to check that steps in a process happen in the right sequence.
unittest.mock’s wrapsTesting terminology distinguishes between different kinds of test doubles, including:
gc.get_objects()Here’s a lovely hack that I’ve used when machete-mode debugging.
WeakKeyDictionaryIn several programs, I’ve wanted to solve the problem of associating extra data with an object. For example, in django-upgrade, the individual “fixer” functions often want to store extra data per visited ast.Module object.
Back in February, I encountered an out-of-memory error while migrating a client project to Python 3.14. The issue occurred when running Django’s database migration command (migrate) on a limited-resource server, and seemed to be caused by the new incremental garbage collection algorithm in Python 3.14.
I’ve made another package! Like icu4py, which I made in February, it was sponsored by my client Rippling. And like tprof, which I made in January, it’s a profiling tool!
I made a new package! Thank you to my client Rippling for inspiring and sponsoring its development.
Profilers measure the performance of a whole program to identify where most of the time is spent. But once you’ve found a target function, re-profiling the whole program to see if your changes helped can be slow and cumbersome. The profiler introduces overhead to execution and you have to pick out the stats for the one function you care about from the report. I have often gone through this loop while optimizing client or open source projects, such as when I optimized Django’s system checks framework (previous post).
SyntaxWarning: 'return' in a 'finally' blockTake this code:
When testing code that outputs to the terminal through either standard out (stdout) or standard error (stderr), you might want to capture that output and make assertions on it. To do so, use contextlib.redirect_stdout() and contextlib.redirect_stderr() to redirect the respective output streams to in-memory buffers that you can then inspect and assert on.
importlib.metadata.version()Sometimes, it’s useful to branch the behaviour of your code based on the version of a package that you have installed. This may be to support an upgrade in your project, or for your own package to support different versions of a dependency.
BrokenPipeError when piping output to other commandsIf you’ve written a Python script that outputs a lot of data, then piped that output into another command that only reads part of it, you might have encountered a BrokenPipeError. For example, take this script:
A neat testing pattern is writing common tests in a base class and then applying them to multiple objects through subclassing. Doing so can help you test smarter and cover more code with less boilerplate.
Python comes with two built-in profilers for measuring the performance of your code: cProfile and profile. They have the same API, but cProfile is a C extension, while profile is implemented in Python. You nearly always want to use cProfile, as it’s faster and doesn’t skew measurements as much.
pre-commit is my favourite Git-integrated “run things on commit” tool. It acts as a kind of package manager, installing tools as necessary from their Git repositories. This makes it fairly easy to set up: all you need to install is pre-commit itself, and it takes things from there.
In Python, a mixin class is a class that is not intended to be used directly, but instead “mixed in” to other classes through multiple inheritance. Mixins are not really a language feature but more of a conventional pattern allowed by Python’s multiple inheritance rules. Unfortunately, adding type hints to mixin classes can be tricky because they implicitly require subclasses to fit a certain shape.