Migration Guide¶
This guide covers the rename / deprecation events that have shipped
since v0.1, ordered newest first. The install_llm_txt /
uninstall_llm_txt installer was removed in 0.5; the 0.4-era
figure constructors (dm.subplots, dm.figure), the agent_utils
and xplot module aliases, the 0.3 width tokens, FS_* figsize
tuples, cm2in, the dartwork_mpl.constant module, and the
figsize= / dpi= arguments they used to accept were all removed
across 0.4.x. Accessing any of them now raises AttributeError /
ModuleNotFoundError / TypeError with a message naming the
replacement. The dartwork_mpl.asset_viz and
dartwork_mpl.helpers.formatting submodule aliases still import with a
DeprecationWarning and are scheduled for removal in v1.0.
At a glance¶
Old surface |
New surface |
|---|---|
|
|
|
|
|
|
|
call |
raw |
|
bare-number width (e.g. |
unit string ( |
|
|
|
iterate explicit widths inline |
|
|
|
|
|
active style preset |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
dm.named removal & color → colors submodule rename¶
dm.named is gone. The replacement is dm.color, a single
string-parser entry point that mirrors dm.length:
# Before
dm.named("oc.red5")
# Now
dm.color("oc.red5") # palette name
dm.color("#ff0000") # hex
dm.color("rgb(1, 0, 0)") # functional rgb
dm.color("oklch(0.7, 0.15, 30)") # functional oklch
dm.color("oklab(0.5, 0.05, 0.05)")
dm.color(some_color_instance) # pass-through
The specialized constructors dm.hex, dm.rgb, dm.oklch,
dm.oklab are unchanged — use them when you already have the
components, just as dm.cm(13) coexists with dm.length("13cm").
The dartwork_mpl.color submodule was renamed to
dartwork_mpl.colors so the color name is free for the new
function. There is no compatibility shim — update direct imports:
# Before
from dartwork_mpl.color import Color
# Now
from dartwork_mpl.colors import Color
Most users never touch the submodule directly (dm.Color,
dm.color, etc. all continue to work via the top-level package).
dm.subplots / dm.figure removal¶
Both dm.subplots and dm.figure were removed. The package no
longer wraps plt.subplots / plt.figure; instead it ships a
single sizing helper that can be passed directly to matplotlib’s
own figsize= argument:
# Before
import dartwork_mpl as dm
fig, ax = dm.subplots(width="13cm", aspect="standard", style="scientific")
# Now
import matplotlib.pyplot as plt
import dartwork_mpl as dm
dm.style.use("scientific")
fig, ax = plt.subplots(figsize=dm.figsize("13cm", "standard"))
Other dm.subplots keyword arguments (sharex, sharey,
width_ratios, height_ratios, gridspec_kw, subplot_kw,
squeeze, nrows, ncols) move to plt.subplots unchanged. The
style= kwarg is gone — call dm.style.use(...) (or
dm.style.stack([...])) before constructing the figure.
dm.figsize(width, aspect) rejects bare int / float widths
explicitly — pass a unit string ("13cm", "5in", "170mm",
"24pt") or a Length value (dm.cm(13), dm.col1, dm.col2)
so the unit is always visible at the call site. The
raw-width-number lint rule catches stragglers.
The two-pass migrator at dm.lint.migrate_legacy_code inserts a
# TODO(dm-migrate): hint above each dm.subplots / dm.figure
call so an agent can rewrite them in one sweep.
v0.4.x → v0.5.0¶
The install_llm_txt installer was removed (#170). It copied the
bundled prompt corpus into IDE-specific folders; the corpus is now read
at runtime instead, so there is nothing to install. dm.install_llm_txt
/ dm.uninstall_llm_txt / dm.INSTALL_TARGETS raise AttributeError.
Removed |
Replacement |
|---|---|
|
|
|
nothing — the corpus is read at runtime, so there is no install to undo |
|
nothing — install targets no longer exist |
ipython is no longer a core dependency (#248). Only dm.show()
(inline SVG display in Jupyter) needs it, so it moved to the notebook
optional extra. dm.show() raises a clear ImportError naming the
extra when IPython is absent; every other entry point is unaffected.
Old install |
New install |
|---|---|
|
|
v0.4.0 → v0.4.1 — API audit round 3 (#141)¶
5 wrapper functions removed using the knowledge-encapsulation criterion: AI agents can reproduce these in one shot without spec.
Removed |
Replacement |
|---|---|
|
|
|
|
|
|
|
inline text loop: |
|
|
|
same shape, y axis: |
v0.4.0 → v0.4.1 — API audit round 2 (#141)¶
8 thin-wrapper utility functions were removed. Each can be replaced by one or two plain matplotlib calls.
Removed |
Replacement |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
For format_axis_thousands, add the following at your callsite:
from matplotlib import ticker
formatter = ticker.FuncFormatter(lambda x, p: f"{x:,.0f}") # sep=","
# Non-comma separator:
# formatter = ticker.FuncFormatter(lambda x, p: f"{x:,.0f}".replace(",", sep))
ax.yaxis.set_major_formatter(formatter) # or ax.xaxis for axis="x"
v0.3.x → v0.4.0¶
[!NOTE] dartwork-mpl has since evolved further:
dm.subplotsanddm.figurethemselves were removed. The snippets below describe the 0.4-era idiom; for the modern call form, see the top section of this guide.
0.4 reshapes the figure-creation surface around two ideas:
Width is free-form. Pass any unit-suffixed string (
"13cm","6.7in","170mm"), a helper call (dm.cm(13),dm.inch(6.7),dm.mm(170)), or the academic-column sugardm.col1/dm.col2. The fixed 4-tierSW/MW/TW/DWconstants are deprecated.Aspect is a height/width ratio, separated from width. Six named tokens cover the common cases; pass a positive float for anything else.
The 0.3 surface is gone, not deprecated. The 0.4.0 cut pulled the planned 0.5.0 removals forward, so the table above marks every 0.3 width / FS /
cm2in/figsize=/dpi=entry as already removed. There is noDeprecationWarninggrace period — old call sites raise immediately. Migrate them all in one pass.
A new dm.lint module checks code against a 15-rule anti-pattern
catalog so editor tooling, MCP clients, and CI all share the same
ground truth.
Width tokens → width="..."¶
# DEPRECATED — fires `width-token` lint warning
fig, ax = plt.subplots(figsize=(dm.SW, dm.SW * 0.75))
# 0.4 — width string, aspect token
fig, ax = dm.subplots(width="9cm", aspect="standard")
# 0.4 — academic column sugar
fig, ax = dm.subplots(width=dm.col1, aspect="standard")
Same idea for the rest of the 4-tier ladder:
0.3 |
0.4 (preferred) |
|---|---|
|
|
|
|
|
|
|
|
|
iterate explicit widths inline |
figsize= → width= + aspect=¶
figsize= is the most common 0.3 idiom and is the single biggest
source of mismatched figures across a multi-figure report. The
figsize-direct lint rule flags any remaining usage:
# DEPRECATED — fires `figsize-direct` lint critical
fig, ax = plt.subplots(figsize=(dm.cm2in(13), dm.cm2in(10)))
# 0.4
fig, ax = dm.subplots(width="13cm", aspect=10 / 13)
FS_* tuples follow the same path:
# DEPRECATED — fires `width-token` lint warning
fig, ax = plt.subplots(figsize=dm.FS_SINGLE)
# 0.4
fig, ax = dm.subplots(width="9cm", aspect="standard")
Aspect tokens¶
Aspect is height ÷ width. Six named tokens are recognised:
Token |
Ratio (h/w) |
Typical use |
|---|---|---|
|
|
scatter, correlation matrices |
|
|
tall multi-row dashboards |
|
|
default: time series, bar/line |
|
|
classic publication figures |
|
|
landscape charts, talks |
|
|
very wide trend strips |
Or pass a positive float directly:
fig, ax = dm.subplots(width="13cm", aspect=0.6)
validate_figure warns on extreme aspects (< 0.3 or > 4.0).
tight_layout → simple_layout¶
# DEPRECATED — fires `tight-layout` lint critical
plt.tight_layout()
fig.tight_layout()
# 0.5+
dm.simple_layout(fig) # snap content flush to figure edges
dm.simple_layout(fig, margin="2%") # uniform 2% buffer
dm.simple_layout(fig, margin=dm.mm(2)) # uniform 2 mm buffer
dm.simple_layout(fig, ml=dm.cm(1), mr="3%") # per-side, mixed units
simple_layout measures every visible artist on every axes
(texts, title, axis labels, view-limited tick labels, axis offset
text, legend) and arithmetically places the GridSpec so the
content union sits at the requested distance from each figure
edge. The result is deterministic — same figure produces the same
GridSpec, no scipy involved. It survives long labels, multi-line
titles, twinx() right-spine cases, and log-scale fixed-points
that tight_layout mangles.
The historical dm.auto_layout(fig) still works as a
:class:DeprecationWarning-emitting alias; new code should call
simple_layout directly.
The previous simple_layout keyword arguments (margins=(...),
bbox=..., bound_margin=..., gtol=..., importance_weights=...)
have been removed in favour of the unified margin /
ml/mr/mt/mb API. See the at-a-glance table at the top of
this guide.
dm.cm2in → dm.cm¶
cm2in(x) converted cm to a plain float. dm.cm(x) returns a
:class:~dartwork_mpl.units.Length value — a Color-pattern wrapper
with multi-unit views (.cm / .mm / .inch / .pt) and
arithmetic that preserves the tag, so dm.cm(9) * 2 stays a
Length and round-trips through parse_width cleanly.
dm.inch(x), dm.mm(x), dm.pt(x) are the analogous helpers for
the other units; dm.length("13cm") parses a unit string.
# DEPRECATED — emits DeprecationWarning
value = dm.cm2in(9)
# 0.4+
length = dm.cm(9) # Length(9.0000cm)
length = dm.inch(3.5) # Length(3.5000in)
length = dm.mm(170) # Length(17.0000cm)
length = dm.pt(24) # Length(0.8467cm)
# Multi-unit views (Color-style):
length.cm # 9.0
length.inch # 3.5433...
length.pt # 255.118...
0.4 in-flight rename. An earlier 0.4 draft used
Inches(float)as a phantom-type marker. It was renamed to :class:Length(a wrapper, no longer afloatsubclass) before any 0.4 release shipped, to align with theColorclass and to expose per-unit views. Top-level constructorsdm.cm/dm.inch/dm.mmkeep the same signatures; they just returnLengthnow.dm.Inchesis no longer importable.
Module renames carried forward¶
The earlier rename pairs (agent_utils → helpers,
xplot → templates, helpers.formatting → helpers.labels,
asset_viz → diagnostics) are still deprecated and continue to
work in 0.4 with a DeprecationWarning. See the v0.1.x → v0.2.0
and v0.3.x sections below for the canonical replacements.
“Zero-Resize Policy” wording is retired¶
Pre-0.4 docs framed figure sizing as a “Zero-Resize Policy”
enforced by the style preset. dartwork-mpl now uses free width
input plus a lint consistency guard (the oversize-width and
raw-width-number rules). Any project rule that still cites the
“Zero-Resize Policy” should be rewritten in terms of
plt.subplots(figsize=dm.figsize(...)) + dm.lint.
New: dm.lint¶
dm.lint.lint(code) runs the 15-rule anti-pattern catalog over a
Python source string. It is the same engine the MCP
lint_dartwork_mpl_code tool and dartwork-mpl lint CLI use, so
your editor, your CI, and your AI assistant all see the same
violations.
import dartwork_mpl as dm
source = """
import matplotlib.pyplot as plt
fig, ax = plt.subplots(figsize=(6.7, 4.0))
plt.tight_layout()
"""
issues = dm.lint.lint(source)
for issue in issues:
print(issue.rule_id, issue.severity, issue.message)
print(dm.lint.format_report(issues))
The full rule list (figsize-direct, tight-layout,
width-token, oversize-width, fontsize-literal,
linewidth-literal, raw-hex-color, jet-cmap, …) lives in
asset/prompt/02-anti-patterns.yaml and is also reachable as the
MCP resource dartwork-mpl://guide/anti-patterns.
v0.1.x → v0.2.0¶
agent_utils → helpers¶
Renamed to make clear these are general-purpose utilities, not AI-agent-specific.
# Old (deprecated — emits DeprecationWarning)
from dartwork_mpl import agent_utils
from dartwork_mpl.agent_utils.colors import auto_select_colors
# New (recommended)
from dartwork_mpl import helpers
from dartwork_mpl.helpers.colors import auto_select_colors
xplot → templates¶
Renamed to better describe its purpose: a small, curated set of ready-to-use plot templates.
# Old (deprecated)
from dartwork_mpl.xplot import plot_diverging_bar
import dartwork_mpl.xplot as xp
# New
from dartwork_mpl.templates import plot_diverging_bar
import dartwork_mpl.templates as tpl
# Or — preferred — top-level
import dartwork_mpl as dm
dm.plot_diverging_bar(...)
v0.3.x¶
helpers.formatting → helpers.labels¶
The formatting submodule of helpers was renamed to labels to
remove a long-standing name clash with the top-level
dartwork_mpl.formatting module (which houses the format_axis_*
tick formatters). The contents (format_axis_labels, optimize_legend,
add_value_labels) are unchanged.
# Old (deprecated)
from dartwork_mpl.helpers.formatting import format_axis_labels
# New
from dartwork_mpl.helpers.labels import format_axis_labels
# Or via the namespace:
import dartwork_mpl as dm
dm.helpers.labels.format_axis_labels(...)
asset_viz → diagnostics¶
The four asset-inspection helpers (classify_colormap,
plot_colormaps, plot_colors, plot_fonts) moved to a single
top-level dartwork_mpl.diagnostics module. The old asset_viz
subpackage is now a thin shim that re-exports the same four names.
Behaviour is unchanged.
# Old (deprecated)
from dartwork_mpl.asset_viz import plot_colors, plot_fonts
# New (canonical)
from dartwork_mpl.diagnostics import plot_colors, plot_fonts
# Best — top-level (was already supported, also unchanged)
import dartwork_mpl as dm
dm.plot_colors()
dm.plot_fonts()
Worth adopting¶
These additions don’t require migration but pay off if you bump into them:
dm.simple_layout(fig, margin=...)¶
simple_layout accepts a margin keyword (and per-side
ml/mr/mt/mb overrides) so you can declare the inset
buffer in the same call:
dm.simple_layout(fig) # flush to figure edges
dm.simple_layout(fig, margin="2%") # uniform 2% buffer
dm.validate_with_fixes(fig)¶
A lightweight quality check that returns and fixes common figure issues (margin asymmetry, pie label cutoff, etc.):
result = dm.validate_with_fixes(fig)
print(result.report())
Silencing legacy warnings¶
If you can’t migrate everything immediately:
import warnings
warnings.filterwarnings(
"ignore",
category=DeprecationWarning,
module="dartwork_mpl",
)
For test runs, instead surface them so you don’t lose track:
python -W default::DeprecationWarning -m pytest
One-shot migration script¶
For larger codebases, run this once to rewrite every deprecated
import in-place. It covers the v0.2.0 / v0.3.x renames; the 0.3→0.4
width token migration is intentionally left for a manual review
because the right replacement (dm.col1 vs width="9cm" vs an
explicit dm.subplots rewrite) depends on the surrounding code:
import re
from pathlib import Path
REPLACEMENTS = [
# Module-level renames
(r"\bdartwork_mpl\.agent_utils\b", "dartwork_mpl.helpers"),
(r"\bdartwork_mpl\.xplot\b", "dartwork_mpl.templates"),
(r"\bdartwork_mpl\.asset_viz\b", "dartwork_mpl.diagnostics"),
# Submodule rename
(
r"\bdartwork_mpl\.helpers\.formatting\b",
"dartwork_mpl.helpers.labels",
),
]
def migrate(directory: str) -> None:
"""Rewrite deprecated imports under *directory* in-place."""
for py in Path(directory).rglob("*.py"):
original = py.read_text()
updated = original
for pattern, replacement in REPLACEMENTS:
updated = re.sub(pattern, replacement, updated)
if updated != original:
py.write_text(updated)
print(f"updated: {py}")
if __name__ == "__main__":
import sys
migrate(sys.argv[1] if len(sys.argv) > 1 else ".")
Save as migrate_dartwork.py and run python migrate_dartwork.py in
your project root. Diff the result with version control, run your
test suite, and commit.
For the 0.4 width / aspect rewrite, run dm.lint.lint(source) on
each file and walk the issues — every flagged line points at the
specific replacement.
Sanity-check before upgrading to v0.5 / v1.0¶
Once 0.5 lands, the 0.3 width tokens (SW, MW, TW, DW,
WIDTHS, FS_*, cm2in) will be removed. v1.0 drops the older
agent_utils / xplot / helpers.formatting / asset_viz
shims as well. You can audit your project for them with:
grep -rE "(dartwork_mpl\.agent_utils|dartwork_mpl\.xplot|dartwork_mpl\.helpers\.formatting|dartwork_mpl\.asset_viz)" \
--include='*.py' .
grep -rE "\bdm\.(SW|MW|TW|DW|WIDTHS|FS_[A-Z]+|cm2in)\b" \
--include='*.py' .
Anything that comes back is something the next breaking release will remove.
Best practices going forward¶
Use top-level imports when available.
dm.simple_layout(fig)is shorter and survives any internal reorganization that keeps the public API stable:import dartwork_mpl as dm dm.simple_layout(fig)
Pin a range, not an exact version. Patch and minor releases shouldn’t break you; majors will:
# pyproject.toml dependencies = ["dartwork-mpl>=0.4,<1.0"]
Surface deprecation warnings in CI — add
-W default::DeprecationWarningto the pytest invocation in your CI workflow so you find legacy usage before the next breaking release forces you to.Run
dm.lintin pre-commit. A 15-rule scan catches the common 0.3-isms (figsize, tight_layout, hex colors, jet cmap) before they hit review.
Getting help¶
Detailed version notes: CHANGELOG
Current API reference: API documentation
Open an issue: GitHub Issues