Skip to main content

pfmg — Python Flatpak Module Generator

A modern, probe-first replacement for flatpak-pip-generator.

Instead of resolving dependencies statically on the host, pfmg installs the package inside a real Flatpak build sandbox, runs ldd on every compiled extension, checks pkg-config, and tests the import. The result is a Flatpak module JSON that you can drop directly into your manifest — with native dependency errors caught before you ever run flatpak-builder.


Requirements

  • Python 3.11+
  • flatpak installed on the host (for generate and inspect)
  • pip3 or uv available on the host (for source collection)

Installation

pip install pfmg

How it works

pfmg generate numpy
         │
         ├─ 1. Install package inside org.freedesktop.Sdk sandbox
         ├─ 2. Run ldd on every .so file → detect missing native libs
         ├─ 3. Run pkg-config on declared deps → detect missing headers / pc files
         ├─ 4. Test the Python import
         ├─ 5. Build-test the generated module (flatpak-builder dry run)
         │      └─ if a build dep is missing and resolvable on PyPI → probe it
         │         and retry automatically (up to 5 times)
         └─ 6. Write module JSON

Errors are matched against a local dataset of SDK profiles, extension profiles, and ready-to-use recipes, so you get actionable suggestions ("add org.freedesktop.Sdk.Extension.rust-stable") instead of raw linker output.


The local dataset

pfmg ships with — and continuously grows — a dataset of:

Directory Contents
data/sdk-profiles/ Profiles of base SDKs (libraries, pkgconfig, executables)
data/ext-profiles/ Profiles of SDK extensions
data/nat-recipes/ Ready-to-use Flatpak module JSON for native libraries (zlib, openssl, …)
data/pip-recipes/ Ready-to-use module JSON for Python packages with known native deps

When pfmg generate encounters an error it queries this dataset and suggests concrete actions: which SDK extension to add, which recipe to prepend to the manifest, or which --build-dep flag to pass.

Use pfmg import, pfmg inspect, and pfmg inspect-all to grow the dataset for your own extensions or SDK versions.

Commands

pfmg generate

Probe one or more Python packages and generate Flatpak module JSON files.

pfmg generate <package> [<package> ...] [OPTIONS]
Option Default Description
--sdk, -s org.freedesktop.Sdk Base SDK to use
--runtime org.freedesktop.Platform Runtime ID
--sdk-version, -V 24.08 SDK branch
--extension, -e — SDK extension to activate (repeatable)
--build-dep, -b — Explicit build-time PyPI dep (repeatable)
--output-dir, -o — Directory to write module JSON files
--format, -f json Output format: json or yaml
--uv / --pip --uv Package installer to use inside the sandbox
--keep off Keep the sandbox work directory after probing
--raw-output, -r off Print raw sandbox stdout/stderr
--verbose, -v off Enable debug logging

Examples:

# Simplest case — latest numpy
pfmg generate numpy

# Pin a version, save the result
pfmg generate numpy==1.26.4 --output-dir ./modules

# Package that needs the Rust toolchain
pfmg generate cryptography \
  --extension org.freedesktop.Sdk.Extension.rust-stable \
  --output-dir ./modules

# Several packages at once on SDK 24.08
pfmg generate pillow lxml --sdk-version 24.08 --output-dir ./modules

# Manually hint a build-time dep (pfmg tries to auto-resolve these,
# but you can be explicit)
pfmg generate some-package --build-dep meson-python --build-dep ninja

When --output-dir is omitted the module JSON is printed to stdout. If pfmg detects errors it prints a resolution table with suggestions from the local dataset.


Search the local dataset for a library, package name, or executable.

pfmg search <query> [OPTIONS]
Option Default Description
--kind, -k all Filter: nat, pip, sdk, ext
--module, -m off Print the full module JSON for matching recipes
pfmg search openssl
pfmg search numpy --kind pip
pfmg search libz  --kind nat
pfmg search clang --kind ext --module

Searches SDK profiles, extension profiles, nat-recipes, and pip-recipes using the same fuzzy matching as the error resolver.


pfmg list

List all entries in the local dataset.

pfmg list [OPTIONS]
Option Default Description
--kind, -k all Filter: nat, pip, sdk, ext
--limit, -n 50 Maximum rows per table
pfmg list
pfmg list --kind nat
pfmg list --kind pip --limit 100

pfmg show

Show the full content of a recipe by its exact ID.

pfmg show <recipe-id> [OPTIONS]
Option Default Description
--kind, -k both Restrict to nat or pip
pfmg show zlib
pfmg show numpy --kind pip

pfmg summarize

Print counts of recipes and profiles in the local dataset.

pfmg summarize

pfmg inspect

Introspect a Flatpak SDK or extension and write a static profile JSON to the local dataset. Profiles are used by the resolver to match errors against known providers.

pfmg inspect <sdk-or-extension-id> [OPTIONS]
Option Default Description
--sdk-branch, -B 25.08 Branch of the base SDK
--ext-branch, -X — Branch of the extension when it differs from --sdk-branch
--output-dir, -o — Override the default profile output directory
--nocleanup off Don't uninstall the extension after probing
--override off Re-probe and overwrite an existing profile

pfmg auto-detects whether the target is a base SDK or an extension by looking for .Extension. in the ID.

Examples:

# Base SDK
pfmg inspect org.freedesktop.Sdk --sdk-branch 24.08

# Extension on the same branch as the SDK
pfmg inspect org.freedesktop.Sdk.Extension.node24 --sdk-branch 25.08

# Extension with its own branch
pfmg inspect org.freedesktop.Sdk.Extension.gcc8 --sdk-branch 24.08 --ext-branch 1.6

Profiles are written to:

data/sdk-profiles/<shortname>.<branch>.json   # base SDKs
data/ext-profiles/<shortname>.<branch>.json   # extensions

pfmg inspect-all

Discover every extension available on a Flatpak remote for the given SDK branches and probe them all.

pfmg inspect-all [OPTIONS]
Option Default Description
--sdk-branch, -B 24.08, 25.08 Branches to probe (repeatable)
--remote, -r flathub Flatpak remote to query
--output-dir, -o — Override profile output directory
--nocleanup off Don't uninstall extensions after probing
--override off Re-probe profiles that already exist

Intended to be run once a year when a new SDK generation ships:

# Update profiles for the two current branches
pfmg inspect-all

# When 26.08 ships
pfmg inspect-all -B 25.08 -B 26.08

Extensions whose profile already exists are skipped unless --override is given.


pfmg import

Import native library and Python recipes from a shared-modules directory (e.g. a checkout of flathub/shared-modules).

pfmg import <modules-dir> [OPTIONS]
Option Default Description
--repo-root, -r . Root of the pfmg repository
--verbose, -v off Enable debug logging
pfmg import ~/src/shared-modules


Metadata

Release files for pfmg 0.8.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 pfmg 0.8.0
File Size Uploaded Provenance Actions
pfmg-0.8.0.tar.gz 78.4 kB Without provenance Details for pfmg-0.8.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for pfmg 0.8.0
File Interpreter ABI Platform Actions
pfmg-0.8.0-py3-none-any.whl Python 3 none any Details for pfmg-0.8.0-py3-none-any.whl

Total release size: 167.0 kB

Release files / pfmg-0.8.0.tar.gz

Download URL pfmg-0.8.0.tar.gz
Size 78.4 kB
Tags Source
SHA-256 checksum
How to use checksums
47bc57e37513171f5fe780adc738b3afcf94a2583b6b821147aba4b215d16673
BLAKE2b-256 checksum
How to use checksums
29596a7ebcadef7831aba4f7a9bec71bdb14f3e1d5ab5cbee3ccc6a8f9393da2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.4

Release files / pfmg-0.8.0-py3-none-any.whl

Download URL pfmg-0.8.0-py3-none-any.whl
Size 88.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
17cf20b772038c36da8b5f8c30e9a2e927bba5b61faa8a24d1c5bc355c3f91d9
BLAKE2b-256 checksum
How to use checksums
a6bca18a1115b495f6b7b44ec91a0b38d2a3654a25f20a08df78a4622d37ec4e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.4

Security for pfmg 0.8.0

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.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.8.0 This release

2 release files No provenance

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