Runtime capability registry for optional Python dependencies
Project description
Pantry
Pantry is a runtime capability registry for optional Python dependencies. It discovers dependency groups from your pyproject.toml, probes which packages are actually installed, and gives you a clean API to check availability, import modules safely, and guard functions with decorators.
Why Pantry?
When your library supports optional features powered by third-party packages, you need to:
| Problem | Without Pantry | With Pantry |
|---|---|---|
| Check if a package is installed | try: import pkg scattered everywhere |
pantry.has("pkg") |
| Import with fallback | Repeated try/except blocks | pantry.get("pkg") |
| Fail with clear message | Custom error handling per feature | pantry["pkg"] raises with install instructions |
| Guard a function | Manual checks at every entry point | @pantry("pkg1", "pkg2") |
| Show what's available | Roll your own reporting | pantry.report() |
Zero configuration — just declare optional dependencies in pyproject.toml as you normally would.
Installation
pip install mypantry
Only runtime dependency: packaging (454 KB, zero transitive deps, already present in most Python environments).
Quick Start
import pantry
# Strict import — raises RuntimeError with install instructions if missing
PIL = pantry["pillow"]
img = PIL.Image.open("photo.jpg")
# Safe import — returns None (or a custom default) if missing
np = pantry.get("numpy")
redis = pantry.get("redis", None)
# Check availability (single or multiple)
if pantry.has("pillow"):
...
if pantry.has("numpy", "pandas"): # all must be available
...
# Guard a function — fails at call-time, not import-time
@pantry("numpy", "pandas")
def analyze(data):
import numpy as np
import pandas as pd
...
# See what's available
print(pantry.report())
Output of report():
pantry report
──────────────────────────────────────────────────────
group package module version ok
imaging pillow PIL 10.4.0 ✓
imaging wand wand - ✗
data numpy numpy 1.26.4 ✓
data pandas pandas 2.1.4 ✓
──────────────────────────────────────────────────────
available: 3/4
How It Works
Pantry reads your standard pyproject.toml optional dependencies:
[project.optional-dependencies]
imaging = ["pillow>=10.0", "wand"]
data = ["numpy>=1.24", "pandas>=2.0"]
cache = ["redis>=5.0"]
When you import pantry, the module:
- Walks up from cwd to find
pyproject.toml - Reads
[project.optional-dependencies] - Probes each package (installed? importable? version?)
- Replaces itself with a
Pantryinstance — so you use it directly
Smart module name resolution handles the pip-name-to-import-name mapping automatically (pillow → PIL, scikit-learn → sklearn, etc.).
Explicit Construction
When you need to target a specific pyproject.toml:
from pantry import Pantry
p = Pantry.from_pyproject("path/to/pyproject.toml")
p = Pantry.discover(start="/my/project")
Lazy Import — Breaking Circular Dependencies
Pantry has a second, independent feature for your own project modules: deferred imports that break circular dependency chains.
# module_a.py — module_b imports module_a, so direct import would cycle
import pantry
pantry.lazy_import("myapp.module_b.Helper")
class Service:
def run(self):
Helper = pantry["myapp.module_b.Helper"] # import happens here
return Helper()
lazy_import just registers the name — no import occurs. The actual import happens
on first pantry["..."] access, when all modules are fully loaded. Results are cached.
This is a bridge toward PEP 690 (Lazy Imports).
Note: Lazy imports are separate from external dependencies.
has(),get(),report()only know about pyproject.toml packages.
API Summary
External Dependencies (pyproject.toml)
| Syntax | Description |
|---|---|
pantry["pkg"] |
Import module; raise RuntimeError if missing |
pantry.get("pkg") |
Import module; return None if missing |
pantry.get("pkg", default) |
Import module; return default if missing |
pantry.has("pkg") |
True if installed and importable |
pantry.has("p1", "p2") |
True if all are available |
pantry.has_group("grp") |
True if any in group is available |
@pantry("p1", "p2") |
Decorator; RuntimeError at call-time if missing |
pantry.report() |
Formatted availability table |
Pantry.discover() |
Explicit construction from auto-discovered pyproject.toml |
Pantry.from_pyproject(path) |
Explicit construction from a specific file |
Lazy Import (own modules)
| Syntax | Description |
|---|---|
pantry.lazy_import("a.b.C") |
Register for deferred import |
pantry["a.b.C"] |
Resolve on first access (cached) |
Key Features
- Zero config — reads standard
pyproject.toml, no extra files or setup - Module-as-instance —
import pantrygives you a ready-to-use object - Smart resolution — pip names mapped to import names automatically
- Multiple access patterns — strict (
[]), safe (.get()), check (.has()) - Decorator guards — fail at call-time with clear install instructions
- Group awareness — check entire dependency groups at once
- Lazy import — break circular dependencies in your own modules
- Availability report — formatted table for diagnostics
- Fully typed — PEP 561
py.typedmarker included
Documentation
Full documentation: mypantry.readthedocs.io
Testing
pip install mypantry[dev]
pytest
Repository Structure
genro-pantry/
├── src/pantry/
│ ├── __init__.py # Module-as-instance bootstrap
│ ├── _discovery.py # pyproject.toml discovery and parsing
│ ├── _probe.py # Package probing and module name resolution
│ ├── _registry.py # Pantry class (query, decorator, report)
│ └── py.typed # PEP 561 marker
├── tests/
├── docs/
├── pyproject.toml
└── LICENSE
Project Status
- Status: Alpha
- Python: 3.11, 3.12, 3.13
- License: Apache 2.0
Contributing
Contributions are welcome. Please open an issue first to discuss what you'd like to change.
License
Copyright 2025 Softwell S.r.l. — Licensed under the Apache License 2.0.
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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file mypantry-0.2.0.tar.gz.
File metadata
- Download URL: mypantry-0.2.0.tar.gz
- Upload date:
- Size: 27.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a18b0f93a1085133989c7c391971eb0e385cfe829729d1bb9ee79c2461cbfe75
|
|
| MD5 |
c8cf3aab75f1f56474af1d88efc26ae0
|
|
| BLAKE2b-256 |
a813f1d21c49b1876891ee0dff9fb895d415edbf36ee6b03d68a85ca79d3e5c1
|
Provenance
The following attestation bundles were made for mypantry-0.2.0.tar.gz:
Publisher:
publish.yml on genropy/genro-pantry
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
mypantry-0.2.0.tar.gz -
Subject digest:
a18b0f93a1085133989c7c391971eb0e385cfe829729d1bb9ee79c2461cbfe75 - Sigstore transparency entry: 1191398467
- Sigstore integration time:
-
Permalink:
genropy/genro-pantry@201f8559d91528c4854ff914e3747fe34cfc20b8 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/genropy
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@201f8559d91528c4854ff914e3747fe34cfc20b8 -
Trigger Event:
push
-
Statement type:
File details
Details for the file mypantry-0.2.0-py3-none-any.whl.
File metadata
- Download URL: mypantry-0.2.0-py3-none-any.whl
- Upload date:
- Size: 14.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3d43090df46499c7375882d78af4ee5321aebd990c4818257525895742dd637c
|
|
| MD5 |
bbe8d90a134ba55e9b7464010d4bf83c
|
|
| BLAKE2b-256 |
1f7b78f1475f4c883ec4cd6b044b53963c111ac9600a22f3b5c4203182c66230
|
Provenance
The following attestation bundles were made for mypantry-0.2.0-py3-none-any.whl:
Publisher:
publish.yml on genropy/genro-pantry
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
mypantry-0.2.0-py3-none-any.whl -
Subject digest:
3d43090df46499c7375882d78af4ee5321aebd990c4818257525895742dd637c - Sigstore transparency entry: 1191398476
- Sigstore integration time:
-
Permalink:
genropy/genro-pantry@201f8559d91528c4854ff914e3747fe34cfc20b8 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/genropy
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@201f8559d91528c4854ff914e3747fe34cfc20b8 -
Trigger Event:
push
-
Statement type: