Cycler

Composable style-cycle library for combining and iterating property values, best known as matplotlib's plot-styling engine

Library
PyPI
v0.12.1
82stars
BSD 3-Clause License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
35/100Needs Attention
Development Activity0
Maintenance20
Community48
Maturity60
Momentum12

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
74/100Good
Architecture75
Code Quality78
Innovation60
Learning Curve82

Cycler is a small Python library for building composable “style cycles”: iterables of dictionaries that pair property names (like color or linestyle) with a sequence of values to rotate through. Individual Cycler objects can be combined with + (zip together, matching position) or * (outer product, all combinations), letting you build rich, declarative styling rules out of simple building blocks.

Cycler was extracted from matplotlib, which uses it internally to drive axes.prop_cycle — the mechanism that decides which color and line style each new plotted line gets. It has no plotting-specific code itself, though, and is a general-purpose tool for any scenario where you need to cycle through combinations of keyword-argument-like values.

What You Get

  • A cycler(key=values) constructor that builds a Cycler object yielding {key: value} dictionaries, one per item in values
  • Composition operators: + (zip-style, position-matched concatenation of keys) and * (outer product across all combinations of keys)
  • A concat() helper for chaining two cyclers end-to-end (like itertools.chain) rather than combining their keys
  • Full typing support (py.typed) with generic Cycler[K, V] type parameters for key and value types
  • Direct integration with matplotlib’s axes.prop_cycle rcParam, which is itself a Cycler instance

Common Use Cases

  • Customizing matplotlib’s default color/linestyle/marker rotation so successive plotted lines follow a specific styling scheme
  • Building combinatorial parameter sweeps for plots (e.g. every color paired with every linestyle) using the * operator
  • Any general iteration task that needs to cycle through structured combinations of keyword-style property values, outside of plotting
  • Concatenating two independently-defined style cycles into one longer cycle with concat()

Under The Hood

Architecture - The library is a single module (cycler/__init__.py, ~580 lines) centered on the Cycler class, which stores an internal list of (keys, iterable-of-values) pairs; __add__ zips two cyclers’ dictionaries together key-by-key (requiring equal length and non-overlapping keys), __mul__ takes their itertools.product() across all value combinations, and __iter__ lazily yields merged dictionaries by walking the stored structure — there is no eager materialization of the full cycle. Tech Stack - Pure Python 3.8+ with zero runtime dependencies, using only itertools, functools, operator, and typing from the standard library; built with a standard pyproject.toml/setuptools-based packaging setup. Code Quality - test_cycler.py (364 lines) exercises composition (+, *), concatenation, equality, repr, indexing, and error cases (overlapping keys, mismatched lengths) with pytest; the module is fully type-annotated using Generic[K, V] and ships py.typed for downstream type checking. API Design - The API purposefully mirrors familiar Python operators (+, *, iteration, indexing, len()) so that composing style cycles reads like ordinary arithmetic on iterables, and the single cycler() factory function covers the common case (cycler(color=[...]), cycler(key, values)) without requiring users to touch the Cycler class directly.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search