mpl-brandpacker
Package your brand design into a matplotlib.pyplot drop-in replacement. Define titles, headers styling, colors, and axes styling as Python classes — mpl-brandpacker handles the patching so your_brand.pyplot.subplots() returns fully branded figures and axes.
Install
pip install mpl-brandpacker
Quick start
1. Define your brand
# my_brand/colors.py
import mpl_brandpacker as mbp
class Colors(mbp.ColorsBase):
primary = "#1a5276"
accent = "#e67e22"
dark = "#2c3e50"
muted = "slategray" # named colors work too
cycle_0 = "C0" # matplotlib cycle colors
highlight = "coral" # CSS named colors
Colors.plot() # → swatch grid for documentation
ColorsBase accepts any matplotlib color string (#RRGGBB, #RRGGBBAA, #RGB, named colors, C0–C9, tab:blue, etc.) and normalizes to #rrggbb at definition time.
# my_brand/sizes.py
from mpl_brandpacker.sizes import MM_TO_INCH
class Sizes(mbp.FigsizesBase):
half = (88 * MM_TO_INCH, 76 * MM_TO_INCH)
full = (181 * MM_TO_INCH, 76 * MM_TO_INCH)
class FontSizes(mbp.SizesBase):
title = 10
body = 8
footer = 6.5
_scalers = {"presentation": 2.0}
SizesBase.scaled() is thread-safe — concurrent threads and async tasks each get their own scaled values.
# my_brand/figure.py
from mpl_brandpacker import BrandFigure, brand_method
class MyFigure(BrandFigure):
@brand_method
def set_title(self, title, **kw):
self.mpl.suptitle(title, fontsize=10, weight="bold", x=0.02, ha="left", **kw)
@brand_method
def set_sources(self, sources, **kw):
self.text(0.02, 0.02, f"Source: {sources}", fontsize=6.5,
color="#888", transform=self.transFigure, **kw)
@brand_method(overwrite="savefig")
def _branded_save(self, *args, **kw):
"""Override savefig with branded defaults.
Pylance still shows the original Figure.savefig docstring
because the implementation is underscore-prefixed.
"""
kw.setdefault("dpi", 300)
kw.setdefault("bbox_inches", "tight")
self.mpl.savefig(*args, **kw)
Use @brand_method(overwrite="name") to override a built-in method while keeping IDE autocompletion on the original.
# my_brand/axes.py
from mpl_brandpacker import BrandAxes, brand_method
class MyAxes(BrandAxes):
@brand_method
def set_xlabel(self, label, **kw):
self.mpl.set_xlabel(label, fontsize=8, **kw)
@brand_method
def set_ylabel(self, label, **kw):
self.mpl.set_ylabel(label, fontsize=8, rotation="horizontal", **kw)
def set_style(ax, **kw):
ax.grid(True, alpha=0.2)
for spine in ("top", "right"):
ax.spines[spine].set_visible(False)
2. Configure
# my_brand/__init__.py
import mpl_brandpacker as mbp
from pathlib import Path
mbp.configure(
figure_cls=MyFigure,
axes_cls=MyAxes,
style_fn=set_style,
stylesheet=Path(__file__).parent, # dir with .mplstyle + data/fonts/
pandas=True, # also hook df.plot()
)
3. Re-export pyplot
# my_brand/pyplot.py
from mpl_brandpacker.pyplot import * # noqa
from mpl_brandpacker.pyplot import gcf
# pyplot-level shortcuts for brand methods (like plt.title in matplotlib)
def title(title, **kw): gcf().set_title(title, **kw)
def subtitle(sub, **kw): gcf().set_subtitle(sub, **kw)
def sources(src, **kw): gcf().set_sources(src, **kw)
def footnote(note, **kw): gcf().set_footnote(note, **kw)
For IDE autocompletion of brand methods on fig and ax, add a pyplot.pyi stub file — see the template for a complete example.
4. Use it
import my_brand.pyplot as plt
fig, ax = plt.subplots()
ax.plot([1, 2, 3], [4, 5, 6])
ax.set_xlabel("Quarter")
plt.title("Revenue")
plt.sources("Bloomberg")
plt.show()
Everything is branded. Original matplotlib methods are accessible via .mpl:
fig.mpl.legend() # original Figure.legend
ax.mpl.set_xlabel() # original Axes.set_xlabel
5. Reset (notebooks)
When iterating on your brand in a notebook, use reset() to start fresh:
import mpl_brandpacker as mbp
mbp.reset() # clears all hooks, reverts pandas
mbp.configure(figure_cls=..., ...) # re-configure
What it provides
| Export | Purpose |
|---|---|
configure() |
Wire everything up — one call |
reset() |
Clear all hooks (for notebook iteration) |
brand_method |
Decorator to auto-register methods for patching |
BrandFigure |
Base class for figure methods (subclass of Figure) |
BrandAxes |
Base class for axes methods (subclass of Axes) |
ColorsBase |
Color enum — accepts any matplotlib color string, normalizes to hex |
FigsizesBase |
Validated (w,h) size enum with .plot() |
SizesBase |
Font sizes with thread-safe context-managed scaling |
PrintableEnum |
Generic enum base |
Submodules (advanced)
| Module | Purpose |
|---|---|
mpl_brandpacker.pyplot |
Branded drop-in for matplotlib.pyplot |
mpl_brandpacker.pandas |
use_for_pandas() for df.plot() |
mpl_brandpacker.patcher |
brand_method, patch_method(), MethodProxy |
mpl_brandpacker.style |
register_stylesheet() |
mpl_brandpacker.sizes |
MM_TO_INCH, POINTS_TO_INCH |
mpl_brandpacker.utils |
get_text_bbox(), separate_kwargs() |
How it works
configure() builds two functions — make_fig(fig) and make_ax(ax) — that patch matplotlib objects using Python's descriptor protocol. When you import my_brand.pyplot as plt, three pyplot entry points are intercepted:
figure()→ patches the new figure + wraps its axes creation methodsgcf()→ patches the current figuregca()→ patches the current axes
All other pyplot functions (subplots, show, savefig, etc.) work unchanged because they internally call figure() or gcf().
@brand_method decorator
@brand_method # patches fig.set_title
def set_title(self, title): ...
@brand_method(overwrite="savefig") # patches fig.savefig with this method
def _branded_save(self, *a, **kw): # underscore name → invisible to Pylance
self.mpl.savefig(*a, dpi=300) # .mpl accesses the original
The overwrite parameter lets you override built-in matplotlib methods while keeping Pylance's autocompletion on the original signature.
Scaffold a new brand
python -m mpl_brandpacker.create_brand acme_corp --author "Jane Doe"
Generates a complete brand package from the built-in template with colors, sizes, figure, axes, header/footer layout, and a pyplot.pyi stub for IDE support.
Template
See template/ for a complete working example.
Metadata
Release files for mpl-brandpacker 0.0.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| mpl_brandpacker-0.0.2.tar.gz | 177.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| mpl_brandpacker-0.0.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 214.9 kB
Release files / mpl_brandpacker-0.0.2.tar.gz
| Download URL | mpl_brandpacker-0.0.2.tar.gz |
|---|---|
| Size | 177.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
96efd7993272e287b246348c245c40c3604a0dafb6ad31cf4aa01dd4a6dce39f
|
|
BLAKE2b-256 checksum How to use checksums |
942c33f578cb9b9e299719ae80141596ee6c7d5b241a1d12d34d0d1e236266d4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
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 Apr 4, 2026.
Transparency logRelease files / mpl_brandpacker-0.0.2-py3-none-any.whl
| Download URL | mpl_brandpacker-0.0.2-py3-none-any.whl |
|---|---|
| Size | 37.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
3430b7c11ec5bcde04519f8278922cde9781eec395ae87e75eebccd54c3bc4ea
|
|
BLAKE2b-256 checksum How to use checksums |
7cd4df412b06b12db143b7a852c0f7dc4928b48bce120d9c9cf8e7d84a3c7e94
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
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 Apr 4, 2026.
Transparency log