Tuesday, March 31, 2026

List outdated packages in Python's pipx without upgrading

pipx does not currently provide a built in method of listing outdated packages. A short bash function shared in an open GitHub issue provides a workaround.

Introduction

I've been using pipx to manage my Python application for roughly three years. As the documentation states, "pipx installs and runs end-user Python apllications(and their respective dependencies) in isolated environments". I'm able to keep my pip list relatively clean as well as isolate my installed applications in separate virtual environments(venvs). Being able to minimize dependency conflicts has alleviated some of the headaches that previously came with installing all my applications and libraries via pip. Since I'm also using pyenv, I can also install them using different Python versions, if necessary.

I do, however, have one nit to pick with pipx. Currently, there is no way to check for available upgrades without actually performing the upgrades. That is, by running pipx upgrade-all and, potentially, upgrading all installed applications. This is time consuming as pipx needs to go through my entire list of installed applications and does not allow me to review upgradeable packages individually. pip has this functionality built in with the command pip list --outdated. There is also a separate package for managing pip package installations called pip-check which I use often and have installed via pipx.

Fortunately, a few years ago, I came across this issue: Feature request: Option to list available upgrades without performing them. While the issue remains open after almost seven years, there is some interesting discussion there as well a couple posts containing workable solutions. I've chosen to implement @StaticPH's comment as my preferred solution.

Solution


pipx-outdated() {
    # See: https://github.com/pypa/pipx/issues/149#issuecomment-684042303
    echo "OUTDATED PACKAGES:"
    while read -sr pyPkgName pyPkgVersion; do
        pyPkgURL="https://pypi.org/pypi/${pyPkgName}/json"
        pypi_latest="$(curl -sS "${pyPkgURL}" | jq --raw-output '.info.version')"
        [ "$pyPkgVersion" != "$pypi_latest" ] && printf "%s\n\tCurrent: \
        %s\tLatest: %s\n" "$pyPkgName" "$pyPkgVersion" "$pypi_latest"
    done <<( pipx list | grep -o 'package.*,' | tr -d ',' | cut -d ' ' -f 2- )
}

The pipx-outdated function greps through the output of pipx list to get the package name and its currently installed version. Next, using curl, it constructs the PyPi package URL and extracts the latest version from the available json file and compares the installed version to the latest. If there is a difference between the two, a list of outdated packages is print out to the console. While this function may ignore dev or alpha release, it is adequate for my use.

At this point, I can selectively upgrade the packages that I am interested or pass pipx upgrade only the packages I choose to upgrade at this time. Adding this to my .bash_aliases file allows me to run this whenever its needed.

Here's an example of the output of the pipx-outdated function showing two packages that have updates available.

  
    ~$ pipx-outdated
    OUTDATED PACKAGES:
    glances
        Current: 4.5.2  Latest: 4.5.3
    hike
        Current: 1.3.0  Latest: 1.4.0
  

I could choose either to upgrade a single package pipx upgrade ruff or I could upgrade both simultaneously with the command pipx upgrade glances ruff.

While it may be convenient to have this feature eventually integrated into the pipx package proper, I'm grateful to the folks who create and share solutions to paper-cuts as well as the developers who maintain and support the pipx package.

Resources

Saturday, February 28, 2026

PostgreSQL: collation version mismatch

Resolving "collation version mismatch" warnings after a PostgreSQL upgrade

Introduction

This article discusses the appearance and resolution of "collation version mismatch" warning messages appearing in the application logs after upgrading a PostgreSQL database.

Here is an abridged example of the warning messages seen in the logs:


WARNING: database "postgres" has a collation version mismatch
DETAIL: The database was created using collation version 2.36,
but the operating system provides version 2.41.
HINT: Rebuild all objects in this database that use the default
collation and run ALTER DATABASE postgres REFRESH COLLATION VERSION,
or build PostgreSQL with the right library version.

This is a great example of application developers providing clear and concise log messages for the end user.

According to the PostgreSQL documentation:

A change in collation definitions can lead to corrupt indexes and other problems because the database system relies on stored objects having a certain sort order. Generally, this should be avoided, but it can happen in legitimate circumstances, such as when upgrading the operating system to a new major version or when using pg_upgrade to upgrade to server binaries linked with a newer version of ICU. When this happens, all objects depending on the collation should be rebuilt, for example, using REINDEX. When that is done, the collation version can be refreshed using the command ALTER COLLATION ... REFRESH VERSION. This will update the system catalog to record the current collation version and will make the warning go away. Note that this does not actually check whether all affected objects have been rebuilt correctly.

Note: For this particular use case, I am running Django(5.2.x) web applications with a PostgreSQL(15.x) database back end within Docker(29.2.1) containers on a Debian testing(trixie) Linux distribution.

Instructions

  1. Update docker-compose.yml with new version of the PostgreSQL database.
    • For example, replace the statement image: postgres:15.11 with image: postgres:15.17.
    • See the official PostgreSQL Docker image page for additional information.
  2. Rebuild the Docker environment: docker compose up --build
  3. Once the build is finished, the warning messages mentioned above will start appearing in the logs.

  4. Make a note of all the databases listed in the log messages that need to be rebuilt. In this case, we have four databases to update:

    • test_django-start
    • template1
    • postgres
    • django-start
  5. Log into the database container:

    sh docker exec -it django_start-db bash

  6. Connect to the first database.

    psql -d test_django-start -U django_admin

  7. Execute the commands appropriate to the connected database.

    ALTER DATABASE "test_django-start" REFRESH COLLATION VERSION;

    REINDEX DATABASE "test_django-start";

    \c template1

    ALTER DATABASE template1 REFRESH COLLATION VERSION;

    REINDEX DATABASE template1;

    \c postgres

    ALTER DATABASE postgres REFRESH COLLATION VERSION;

    REINDEX DATABASE postgres;

    \c django-start

    ALTER DATABASE "django-start" REFRESH COLLATION VERSION;

    REINDEX DATABASE "django-start";

    \q # quit psql

    exit # exit container

  8. Restart the database container.

    docker stop django_start-db docker start django_start-db

Further Reading