Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 10 additions & 6 deletions ultraplot/constructor.py
Original file line number Diff line number Diff line change
Expand Up @@ -881,10 +881,10 @@ def _parse_basic_properties(self, kwargs):

def _handle_empty_args(self, props, kwargs):
"""Handle case when no positional arguments are provided."""
props.setdefault("color", "black")
props.setdefault("color", ["black"])
if kwargs:
warnings._warn_ultraplot(f"Ignoring Cycle() keyword arg(s) {kwargs}.")
self._build_cycler(())
self._build_cycler((props,))

def _handle_cycler_args(self, args, props, kwargs):
"""Handle case when arguments are cycler objects."""
Expand Down Expand Up @@ -928,13 +928,17 @@ def _build_cycler(self, dicts):
props.setdefault(key, []).extend(value)
# Build cycler with matching property lengths
# Ensure at least a default color property exists
if not props:
props = {"color": ["black"]}

# Build cycler with matching property lengths
lengths = [len(value) for value in props.values()]
maxlen = np.lcm.reduce(lengths)
props = {key: value * (maxlen // len(value)) for key, value in props.items()}
props = {
key: value * (maxlen // len(value))
for key, value in props.items()
if len(value)
}
# Set default color property if not present
if "color" not in props or not props:
props = {"color": ["black"]}
mcycler = cycler.cycler(**props)
super().__init__(mcycler)

Expand Down
14 changes: 14 additions & 0 deletions ultraplot/tests/test_constructor.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ def test_not_allowed_keyword():
def test_cycler_edge_cases():
"""Test edge cases and error conditions"""
# Test with empty lists
cycle = uplt.Cycle()
assert cycle.get_next() == dict(color="black") # default fallback
cycle = uplt.Cycle(color=[])
assert cycle.get_next() == dict(color="black") # default fallback
cycle = uplt.Cycle(colors=[])
assert cycle.get_next() == dict(color="black") # default fallback

Expand All @@ -74,6 +78,7 @@ def test_cycler_edge_cases():
props1 = cycle.get_next()
props2 = cycle.get_next()
assert props1["marker"] == props2["marker"] # marker should stay same
assert props1["color"] == "red"
assert props1["color"] != props2["color"] # color should cycle


Expand Down Expand Up @@ -108,3 +113,12 @@ def test_pass_on_cycle():
for color in colors:
assert color == active_cycle.get_next()["color"]
assert color == cycle.get_next()["color"]

colors = ["red", "green", "black"]
cycle = uplt.Cycle(color=colors)
fig, ax = uplt.subplots()
ax.set_prop_cycle(cycle)
active_cycle = ax.axes._active_cycle
for color in colors:
assert color == active_cycle.get_next()["color"]
assert color == cycle.get_next()["color"]