Skip to main content

Python Flatpak Module Generator — a probe-first replacement for flatpak-pip-generator

Project description

pfmg — Python Flatpak Module Generator

[!WARNING] For the sake of honesty, it's important to say that most of the code in this package was written by Claude. Although I reviewed the code in general, I didn't review every single line in detail. Please use it accordingly and report any issues you find.

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.


pfmg search

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


Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pfmg-0.8.0.tar.gz (78.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pfmg-0.8.0-py3-none-any.whl (88.6 kB view details)

Uploaded Python 3

File details

Details for the file pfmg-0.8.0.tar.gz.

File metadata

  • Download URL: pfmg-0.8.0.tar.gz
  • Upload date:
  • Size: 78.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.4

File hashes

Hashes for pfmg-0.8.0.tar.gz
Algorithm Hash digest
SHA256 47bc57e37513171f5fe780adc738b3afcf94a2583b6b821147aba4b215d16673
MD5 bdaa18c4c2b2b878c1d8886b83259744
BLAKE2b-256 29596a7ebcadef7831aba4f7a9bec71bdb14f3e1d5ab5cbee3ccc6a8f9393da2

See more details on using hashes here.

File details

Details for the file pfmg-0.8.0-py3-none-any.whl.

File metadata

  • Download URL: pfmg-0.8.0-py3-none-any.whl
  • Upload date:
  • Size: 88.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.4

File hashes

Hashes for pfmg-0.8.0-py3-none-any.whl
Algorithm Hash digest
SHA256 17cf20b772038c36da8b5f8c30e9a2e927bba5b61faa8a24d1c5bc355c3f91d9
MD5 a9d80662c50d99f9a218720bdde79524
BLAKE2b-256 a6bca18a1115b495f6b7b44ec91a0b38d2a3654a25f20a08df78a4622d37ec4e

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page