Skip to main content

Backpack Checker

Logo

Rationale

Let's be honest... I made this mainly to try out the amazing Textual on something. But there's some merit to it (if you look hard enough :D). When working with a team, you might want to rely on a tool, like saying, "everyone, let's install uv or hatch so we can work with inline script metadata." Half of your team will ask you three months later how to run your script... not to mention any newcomers.

And yeah, there are tools—or should I say frameworks—like Nix and similar ones. But I don't care how you got the tool or what machine/system you are using. I only care to know if I can rely on the fact that everyone can use Docker Compose in a specific version.

There might be better tools for this, but I didn't look. Anyway, if you find this useful, that's awesome—it's here for you to use.

Usage

What this provides is a bunch of Check classes and a TUI application made with the amazing Textual (honestly, the tool itself is great, but the way it was made is something else...).

The idea is to install it however you prefer and write a backpack.py script. Probably the most convenient method would be to use the aforementioned inline script metadata:

# /// script
# requires-python = ">=3.12"
# dependencies = [
#   "backpack-checker",
# ]
# ///
import json
from backpack_checker.app import BackpackApp
from backpack_checker.checker import (
    And,
    Check,
    DockerContainerRunning,
    EnvVarsRequired,
    EnvVarsSuggested,
    MinimalVersionCheck,
    Necessity,
    Or,
    SubprocessCheck,
)
from semver import Version

class UVCheck(MinimalVersionCheck):
    _name = "Check if `uv` is installed"
    _explanation = "Check if Docker Compose is installed"
    command = "uv version --output-format=json"
    necessity = Necessity.SUGGESTED

    async def validate(self, result: str) -> bool:
        return self.minimal_version <= Version.parse(json.loads(result)["version"])


app = BackpackApp(
    checks=[UVCheck("0.5.8")]
)
if __name__ == "__main__":
    app.run()

and run it with uv run backpack.py or hatch run backpack.py.

Checkers

You can use the premade checkers. To do that, you'll need to define some data for them.

As you'll see in the examples below, you can customize these extensively: you can create a __init__ method to provide arguments to the checker or override the name and explanation properties to make the messaging dynamic.

For example:

SubprocessCheck

from backpack_checker.checker import SubprocessCheck, Necessity

class AWSLocal(SubprocessCheck):
    _name = "Check if `awslocal` is installed"
    _explanation = """\
AWS Local is a wrapper for the AWS CLI that allows you to interface with AWS instances 
running locally, e.g., with Localstack.

More about awslocal [here](https://github.com/localstack/awscli-local?tab=readme-ov-file#example).
"""
    necessity = Necessity.SUGGESTED
    command = "awslocal --version"

This checks if the awslocal --version command executes with return code 0. The message is designed to provide instructions for backpack users. You can use Markdown when defining the name and explanation. The necessity attribute (default is Necessity.REQUIRED) will only throw a warning (painted yellow) and mark the failure as non-critical.

[!TIP]
In this example, I'm suggesting you install awslocal. But if you'd rather use aws --endpoint-url=http://localhost:4566, that's fine too.

MinimalVersionCheck

You can also use a derivative of SubprocessCheck, called MinimalVersionCheck, to check for the existence of a tool and enforce a minimal semantic version.

from backpack_checker.checker import MinimalVersionCheck

class DockerComposeCheck(MinimalVersionCheck):
    _name = "Check if `docker-compose` is installed"
    _explanation = "Check if Docker Compose is installed"
    command = "docker-compose --version --short"

app = BackpackApp(
    checks=[
        DockerComposeCheck("2.20.3"),
    ]
)

If a command doesn't directly return something like 2.20.3 (as docker-compose --version --short does), you can override the validate method:

from semver import Version
from backpack_checker.checker import MinimalVersionCheck

class UVCheck(MinimalVersionCheck):
    _name = "Check if `uv` is installed"
    _explanation = "Check if UV is installed"
    command = "uv version --output-format=json"

    async def validate(self, result: str) -> bool:
        return self.minimal_version <= Version.parse(json.loads(result)["version"])

app = BackpackApp(
    checks=[
        UVCheck("0.5.8"),
    ]
)

DockerContainerRunning

Another checker is DockerContainerRunning, which uses the Docker SDK for Python to interact with your Docker engine and query running containers. It effectively invokes docker.from_env().containers.list(filters=self.container_list_filters).

class LocalstackRunning(DockerContainerRunning):
    _name = "Check if Localstack is running"
    _explanation = """..."""
    container_list_filters = {"status": "running", "name": "localstack"}

EnvVarsRequired and EnvVarsSuggested

These check whether specific environment variables are set:

UV_EXTRA_INDEX_URL_EXPLANATION = """..."""
PIP_EXTRA_INDEX_URL_EXPLANATION = """..."""

app = BackpackApp(
    checks=[
        EnvVarsRequired(
            "Check if `UV_EXTRA_INDEX_URL` env var is set",
            ["UV_EXTRA_INDEX_URL"],
            UV_EXTRA_INDEX_URL_EXPLANATION,
        ),
        EnvVarsSuggested(
            "Check if `PIP_EXTRA_INDEX_URL` env var is set",
            ["PIP_EXTRA_INDEX_URL"],
            PIP_EXTRA_INDEX_URL_EXPLANATION,
        ),
    ]
)

And/Or Checkers

You can also group checks using And or Or:

from backpack_checker.checker import MinimalVersionCheck, Or

class _DockerComposeCheck(MinimalVersionCheck):
    _name = ""
    _explanation = ""
    command = "docker-compose --version --short"

class _DockerComposeCheck2(_DockerComposeCheck):
    _name = ""
    command = "docker compose version --short"

class OrDockerCompose(Or[str]):
    _name = "Check if `docker compose` or `docker-compose` are installed"

    @property
    def explanation(self) -> str:
        return f"""\
This check ensures either `docker-compose` or `docker compose` is installed. 
Additionally, the version must be at least `{self.minimal_version}`, which supports 
features like the `include` directive with relative paths in `docker-compose.yml` files. 
We rely on that feature.
"""

    def __init__(self, minimal_version: Version | str):
        super().__init__()
        self.minimal_version = minimal_version
        self.checks = [
            _DockerComposeCheck(minimal_version),
            _DockerComposeCheck2(minimal_version),
        ]

app = BackpackApp(
    checks=[
        OrDockerCompose("2.20.3")
    ]
)

The Or checker returns True if any outcome is positive, while the And checker succeeds only if all outcomes are successful.

What would be cool

If I ever have time to play with this again, I’d probably:

  • Separate the UI (TUI) from the checking process.
    • Allow running the checker with a JSON result usable by the UI (potentially multiple UIs).
  • Create a CLI entry point that works like backpack check path/to/your/backpack.py.
  • Add some test coverage here—it would be cool...

Release files for backpack-checker 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for backpack-checker 0.1.0
File Size Uploaded
backpack_checker-0.1.0.tar.gz 66.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for backpack-checker 0.1.0
File Interpreter ABI Platform
backpack_checker-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 76.5 kB

Release files / backpack_checker-0.1.0.tar.gz

Download URL backpack_checker-0.1.0.tar.gz
Size 66.1 kB
Tags Source
SHA-256 checksum
How to use checksums
7ce3d175a0b66c1cd05e4e5decd4b2538d2be65345bbdf5f7baa4a70f2e3383c
BLAKE2b-256 checksum
How to use checksums
f1cdb164686fc27bf066f5e7a783b83838479a7fd6f7bb812f27683de79b21d2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.0.1 CPython/3.12.8

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Dec 31, 2024.

Transparency log

Release files / backpack_checker-0.1.0-py3-none-any.whl

Download URL backpack_checker-0.1.0-py3-none-any.whl
Size 10.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
d9f937ea706db707062dcfea4eef8dbd603fddaee03e5c12e5ff3ccea813a9c1
BLAKE2b-256 checksum
How to use checksums
29f2dc06b6497acecce7c4a60486eeefbcf8ea1703b66f02e8725f3c8c271270
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.0.1 CPython/3.12.8

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Dec 31, 2024.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page