Runtime capability registry for optional Python dependencies
Project description
mypantry
mypantry is lightweight syntactic sugar (~300 lines, zero dependencies) for working with optional Python packages at runtime. It wraps importlib.metadata to check availability, import modules safely, and guard functions with decorators.
Works everywhere — development, installed packages, Docker containers. No configuration files needed.
The entire source is one file: _registry.py. Read it in 10 minutes.
Why mypantry?
| Without mypantry | With mypantry |
|---|---|
try: import pkg + flag + if/raise |
pantry.has("pkg") |
| Repeated try/except blocks | pantry.get("pkg") |
| Custom error handling per feature | pantry["pkg"] raises with install instructions |
| Manual checks at every entry point | @pantry("pkg1", "pkg2") |
| Move imports inside functions for circular deps | pantry.lazy_import("my.module.Class") |
Installation
pip install mypantry
Zero dependencies. Only Python standard library (importlib.metadata).
Recommended Pattern
import pantry
# Guard imports at the top of the file
if pantry.has("numpy"):
import numpy as np
if pantry.has("pillow"):
from PIL import Image
# Guard functions with the decorator
@pantry("numpy", "pillow")
def process(path):
img = Image.open(path)
return np.array(img)
This pattern gives you:
- pipreqs sees the real imports and detects dependencies correctly
- IDE autocompletion works because the imports are standard Python
- pantry provides clean error messages if a dependency is missing
Quick Start
import pantry
# Check if a package is installed (metadata only, no import)
pantry.has("numpy") # True/False
pantry.has("numpy", "pandas") # True only if ALL installed
# Import a module — raises RuntimeError with install instructions if missing
PIL = pantry["pillow"]
# Import safely — returns None (or a default) if missing
np = pantry.get("numpy")
redis = pantry.get("redis", None)
# Get version
pantry.version("numpy") # "1.26.4" or None
# Guard a function
@pantry("numpy", "pandas")
def analyze(data):
...
# See what you've checked
print(pantry.report())
# Or check specific packages
print(pantry.report("numpy", "pandas", "pillow", "redis"))
Output of report():
pantry report
──────────────────────────────────────────────
package module version ok
numpy numpy 1.26.4 ✓
pandas pandas 2.1.4 ✓
pillow PIL 10.4.0 ✓
redis redis - ✗
──────────────────────────────────────────────
available: 3/4
How It Works
import pantry creates a Pantry instance that probes packages on demand using importlib.metadata. No configuration files, no startup scanning.
has()— checks distribution metadata only (fast, no import)get()/[]— imports the module lazily on first access, then caches it- Smart module name resolution:
pillow→PIL,scikit-learn→sklearn, etc.
Works in any context: development, installed packages, Docker, notebooks, REPLs.
Lazy Import — Breaking Circular Dependencies
A separate feature for your own project modules: deferred imports that break circular dependency chains.
# myapp/module_a.py
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()
This does not make external dependencies lazy. It is specifically for breaking circular imports between your own modules. Bridge toward PEP 690.
Lazy imports are separate from external dependencies.
has(),get(),report()do not interact with them.
Testing with simulate_missing
def test_fallback():
with pantry.simulate_missing("numpy"):
assert pantry.has("numpy") is False
assert pantry.has("numpy") is True
API Summary
External Dependencies
| Syntax | Description |
|---|---|
pantry.has("pkg") |
True if installed (metadata check, no import) |
pantry.has("p1", "p2") |
True if all are installed |
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.version("pkg") |
Installed version string, or None |
@pantry("p1", "p2") |
Decorator; RuntimeError at call-time if missing |
pantry.report(...) |
Formatted availability table |
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) |
Testing
| Syntax | Description |
|---|---|
with pantry.simulate_missing("pkg") |
Temporarily hide packages |
Key Features
- Zero dependencies — pure Python standard library
- ~300 lines — one file, fully readable
- No configuration — no pyproject.toml scanning, works everywhere
- On-demand probing —
import pantryis instant, no startup cost - 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
- Lazy import — break circular dependencies in your own modules
- simulate_missing — context manager for testing fallback behavior
- 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 (25 lines)
│ ├── _registry.py # The entire API (303 lines)
│ └── py.typed # PEP 561 marker
├── tests/ # 432 lines, 57 tests, 87% coverage
├── docs/
├── pyproject.toml
└── LICENSE
Project Status
- Status: Beta
- Python: 3.11, 3.12, 3.13
- License: MIT
Contributing
Contributions and feedback welcome. Please open an issue first.
License
Copyright (c) 2025 Softwell S.r.l. — MIT License.
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.5.1.tar.gz.
File metadata
- Download URL: mypantry-0.5.1.tar.gz
- Upload date:
- Size: 20.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5dc9decb45982f0f1596ff99bf6dfaf20eda40a65f740c053a184df9bcd23bd8
|
|
| MD5 |
8e0478def9d05d57072a3287204c4dca
|
|
| BLAKE2b-256 |
93e6c62ebc7f1197d58ee3dae3152aed0017aacd882fb60e440b5797cde19e4a
|
Provenance
The following attestation bundles were made for mypantry-0.5.1.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.5.1.tar.gz -
Subject digest:
5dc9decb45982f0f1596ff99bf6dfaf20eda40a65f740c053a184df9bcd23bd8 - Sigstore transparency entry: 1206565033
- Sigstore integration time:
-
Permalink:
genropy/genro-pantry@213a190c85a69eff40ba185d4c35e33373ef0909 -
Branch / Tag:
refs/tags/v0.5.1 - Owner: https://github.com/genropy
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@213a190c85a69eff40ba185d4c35e33373ef0909 -
Trigger Event:
push
-
Statement type:
File details
Details for the file mypantry-0.5.1-py3-none-any.whl.
File metadata
- Download URL: mypantry-0.5.1-py3-none-any.whl
- Upload date:
- Size: 9.2 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 |
e717e72bc894c4ac501f7cb0aac6d9b5cef6a0f94e12ff42707c7fecaeade73b
|
|
| MD5 |
10ca4b5f40c5324b1f59ea48360eff74
|
|
| BLAKE2b-256 |
9b1a2a990e99bb043b9dbcd781a939ff2f96085ade1293c983e9ac8f8e46656c
|
Provenance
The following attestation bundles were made for mypantry-0.5.1-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.5.1-py3-none-any.whl -
Subject digest:
e717e72bc894c4ac501f7cb0aac6d9b5cef6a0f94e12ff42707c7fecaeade73b - Sigstore transparency entry: 1206565084
- Sigstore integration time:
-
Permalink:
genropy/genro-pantry@213a190c85a69eff40ba185d4c35e33373ef0909 -
Branch / Tag:
refs/tags/v0.5.1 - Owner: https://github.com/genropy
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@213a190c85a69eff40ba185d4c35e33373ef0909 -
Trigger Event:
push
-
Statement type: