Skip to content

Conversation

@codeflash-ai
Copy link

@codeflash-ai codeflash-ai bot commented Dec 4, 2025

📄 30% (0.30x) speedup for _is_single_color in pandas/plotting/_matplotlib/style.py

⏱️ Runtime : 517 microseconds 397 microseconds (best of 140 runs)

📝 Explanation and details

The optimized code achieves a 30% speedup through two key optimizations:

1. ColorConverter instance caching: The original code created a new matplotlib.colors.ColorConverter() instance on every call to _is_single_string_color. The optimized version caches this instance as a module-level variable _conv. This eliminates repeated object instantiation overhead, which the profiler shows reduced time from 43,939ns to 15,090ns per call in _is_single_string_color.

2. More efficient validation in _is_floats_color: The original version used a chained boolean expression with all() which creates a generator and evaluates all elements even when early failures occur. The optimized version restructures the logic with early returns:

  • Checks is_list_like(color) first and returns False immediately for non-sequences
  • Validates length (n != 3 and n != 4) before any iteration
  • Uses an explicit for loop with early return instead of all(), avoiding generator overhead

The profiler shows this reduced _is_floats_color execution time from 522,257ns to 358,781ns total.

Impact on workloads: The function references show _is_single_color is called from _get_colors_from_color and _gen_list_of_colors_from_iterable, indicating it's in a hot path for color processing in matplotlib plotting. The test results show particularly strong improvements (50-70% faster) for RGB/RGBA tuple validation, which are common in plotting workflows. The optimizations are most beneficial when processing many color inputs or when _is_single_string_color is called frequently, making this especially valuable for plotting operations that handle multiple colors or are called repeatedly.

Correctness verification report:

Test Status
⚙️ Existing Unit Tests 🔘 None Found
🌀 Generated Regression Tests 189 Passed
⏪ Replay Tests 🔘 None Found
🔎 Concolic Coverage Tests 🔘 None Found
📊 Tests Coverage 100.0%
🌀 Generated Regression Tests and Runtime
from __future__ import annotations


# imports
from pandas.plotting._matplotlib.style import _is_single_color

# unit tests

# --- BASIC TEST CASES ---


def test_named_color_string():
    # Named color string should be recognized
    codeflash_output = _is_single_color("red")  # 4.46μs -> 3.38μs (31.9% faster)
    codeflash_output = _is_single_color("blue")  # 1.14μs -> 776ns (46.5% faster)
    codeflash_output = _is_single_color("firebrick")  # 924ns -> 593ns (55.8% faster)


def test_alias_color_string():
    # Short alias color strings should be recognized
    codeflash_output = _is_single_color("r")  # 3.12μs -> 2.44μs (27.7% faster)
    codeflash_output = _is_single_color("g")  # 1.10μs -> 832ns (32.3% faster)
    codeflash_output = _is_single_color("b")  # 812ns -> 623ns (30.3% faster)


def test_cN_color_string():
    # 'C0', 'C1', etc. matplotlib color cycle
    codeflash_output = _is_single_color("C0")  # 13.7μs -> 11.4μs (20.3% faster)
    codeflash_output = _is_single_color("C7")  # 5.55μs -> 4.62μs (20.1% faster)


def test_rgb_tuple():
    # Tuple of 3 floats should be recognized
    codeflash_output = _is_single_color(
        (0.1, 0.2, 0.3)
    )  # 3.37μs -> 2.13μs (58.0% faster)
    codeflash_output = _is_single_color(
        [0.1, 0.2, 0.3]
    )  # 1.18μs -> 716ns (64.8% faster)
    codeflash_output = _is_single_color([1, 0, 0])  # 776ns -> 458ns (69.4% faster)
    codeflash_output = _is_single_color(
        (1.0, 0.0, 0.0)
    )  # 897ns -> 539ns (66.4% faster)


def test_rgba_tuple():
    # Tuple of 4 floats should be recognized
    codeflash_output = _is_single_color(
        (0.1, 0.2, 0.3, 0.4)
    )  # 2.62μs -> 1.69μs (55.8% faster)
    codeflash_output = _is_single_color(
        [0.1, 0.2, 0.3, 0.4]
    )  # 1.23μs -> 740ns (66.2% faster)
    codeflash_output = _is_single_color([1, 0, 0, 1])  # 827ns -> 510ns (62.2% faster)


def test_invalid_string_color():
    # Invalid color strings should not be recognized
    codeflash_output = _is_single_color("notacolor")  # 15.6μs -> 12.9μs (21.2% faster)
    codeflash_output = _is_single_color("12345")  # 6.42μs -> 5.21μs (23.3% faster)
    codeflash_output = _is_single_color("")  # 5.12μs -> 4.24μs (20.9% faster)


def test_non_color_tuple():
    # Tuples of wrong length should not be recognized
    codeflash_output = _is_single_color((0.1, 0.2))  # 1.63μs -> 1.32μs (23.3% faster)
    codeflash_output = _is_single_color(
        (0.1, 0.2, 0.3, 0.4, 0.5)
    )  # 553ns -> 444ns (24.5% faster)
    # Tuples of correct length but wrong types should not be recognized
    codeflash_output = _is_single_color(
        ("red", "green", "blue")
    )  # 1.73μs -> 741ns (133% faster)
    codeflash_output = _is_single_color(
        (None, None, None)
    )  # 666ns -> 371ns (79.5% faster)


def test_list_of_colors():
    # List of valid color strings should not be recognized as single color
    codeflash_output = _is_single_color(
        ["red", "blue"]
    )  # 1.08μs -> 869ns (24.1% faster)
    codeflash_output = _is_single_color(
        ["r", "g", "b"]
    )  # 1.66μs -> 734ns (125% faster)
    # List of valid float tuples should not be recognized as single color
    codeflash_output = _is_single_color(
        [(1, 0, 0), (0, 1, 0)]
    )  # 392ns -> 293ns (33.8% faster)


def test_dict_input():
    # Dict input should not be recognized as single color
    codeflash_output = _is_single_color(
        {"r": 1, "g": 0, "b": 0}
    )  # 2.79μs -> 1.71μs (63.2% faster)


def test_none_input():
    # None input should not be recognized as single color
    codeflash_output = _is_single_color(None)  # 1.05μs -> 937ns (11.8% faster)


def test_integer_input():
    # Integer input should not be recognized as single color
    codeflash_output = _is_single_color(5)  # 1.07μs -> 912ns (17.5% faster)


def test_float_input():
    # Single float should not be recognized as single color
    codeflash_output = _is_single_color(0.5)  # 1.01μs -> 891ns (13.2% faster)


def test_tuple_with_non_numeric_types():
    # Tuple with non-numeric types should not be recognized
    codeflash_output = _is_single_color(
        (0.1, 0.2, "blue")
    )  # 3.16μs -> 1.87μs (69.2% faster)
    codeflash_output = _is_single_color(
        (0.1, "green", 0.3)
    )  # 1.06μs -> 646ns (63.6% faster)


# --- EDGE TEST CASES ---


def test_empty_tuple_list():
    # Empty tuple/list should not be recognized
    codeflash_output = _is_single_color(())  # 1.43μs -> 1.21μs (18.4% faster)
    codeflash_output = _is_single_color([])  # 554ns -> 458ns (21.0% faster)


def test_tuple_with_nan_inf():
    # Tuple with NaN or inf should be recognized as single color if all are numeric
    import math

    codeflash_output = _is_single_color(
        (math.nan, 0.2, 0.3)
    )  # 2.63μs -> 1.62μs (62.5% faster)
    codeflash_output = _is_single_color(
        (0.1, math.inf, 0.3)
    )  # 1.02μs -> 641ns (59.4% faster)
    # But tuple with non-numeric should not
    codeflash_output = _is_single_color(
        (math.nan, "red", 0.3)
    )  # 1.20μs -> 633ns (89.3% faster)


def test_tuple_with_negative_numbers():
    # Negative numbers are valid as colors in matplotlib (though may not display correctly)
    codeflash_output = _is_single_color(
        (-1.0, 0.0, 0.0)
    )  # 2.41μs -> 1.59μs (51.9% faster)
    codeflash_output = _is_single_color(
        (0.0, -1.0, 0.0, 1.0)
    )  # 1.34μs -> 798ns (67.9% faster)


def test_tuple_with_large_numbers():
    # Large numbers are valid as colors, but may be out of displayable range
    codeflash_output = _is_single_color((1000, 0, 0))  # 2.42μs -> 1.51μs (60.3% faster)
    codeflash_output = _is_single_color(
        (0, 1000, 0, 1000)
    )  # 1.20μs -> 714ns (68.1% faster)


def test_tuple_with_mixed_int_float():
    # Mixture of int and float types
    codeflash_output = _is_single_color((1, 0.0, 0))  # 2.32μs -> 1.50μs (54.3% faster)
    codeflash_output = _is_single_color(
        [0, 1.0, 0.5, 1]
    )  # 1.42μs -> 876ns (62.2% faster)


def test_tuple_with_bool():
    # Bool is subclass of int, so should be accepted
    codeflash_output = _is_single_color(
        (True, False, True)
    )  # 2.69μs -> 1.78μs (51.0% faster)
    codeflash_output = _is_single_color(
        [False, True, False, True]
    )  # 1.36μs -> 825ns (65.2% faster)


def test_tuple_with_object():
    # Tuple with object type should not be recognized
    class Dummy:
        pass

    codeflash_output = _is_single_color(
        (Dummy(), 0.2, 0.3)
    )  # 3.03μs -> 1.91μs (58.4% faster)


def test_bytes_input():
    # Bytes should not be recognized as single color
    codeflash_output = _is_single_color(b"red")  # 1.28μs -> 1.10μs (16.2% faster)
    codeflash_output = _is_single_color(
        b"\x01\x02\x03"
    )  # 526ns -> 403ns (30.5% faster)


def test_set_input():
    # Set should not be recognized as single color
    codeflash_output = _is_single_color(
        {0.1, 0.2, 0.3}
    )  # 3.07μs -> 2.06μs (49.2% faster)


def test_tuple_with_none():
    # Tuple containing None should not be recognized
    codeflash_output = _is_single_color(
        (0.1, None, 0.3)
    )  # 2.83μs -> 1.73μs (63.8% faster)


# --- LARGE SCALE TEST CASES ---


def test_large_rgb_tuple():
    # Tuple/list with more than 4 elements should not be recognized
    codeflash_output = _is_single_color(
        tuple([0.1] * 5)
    )  # 1.56μs -> 1.36μs (14.3% faster)
    codeflash_output = _is_single_color([0.2] * 10)  # 563ns -> 463ns (21.6% faster)


def test_large_list_of_colors():
    # Large list of color strings should not be recognized as single color
    color_list = ["red"] * 1000
    codeflash_output = _is_single_color(color_list)  # 1.11μs -> 946ns (17.1% faster)


def test_large_list_of_rgb_tuples():
    # Large list of rgb tuples should not be recognized as single color
    rgb_list = [(0.1, 0.2, 0.3)] * 1000
    codeflash_output = _is_single_color(rgb_list)  # 1.14μs -> 955ns (19.4% faster)


def test_large_tuple_of_numbers():
    # Large tuple of numbers should not be recognized as single color
    codeflash_output = _is_single_color(
        tuple([0.1] * 1000)
    )  # 1.68μs -> 1.50μs (11.6% faster)


def test_large_valid_rgb_tuple():
    # Tuple of exactly 3 floats, even if large values, should be recognized
    codeflash_output = _is_single_color(
        (999999.0, 888888.0, 777777.0)
    )  # 2.92μs -> 1.74μs (68.2% faster)


def test_large_valid_rgba_tuple():
    # Tuple of exactly 4 floats, even if large values, should be recognized
    codeflash_output = _is_single_color(
        (999999.0, 888888.0, 777777.0, 666666.0)
    )  # 2.74μs -> 1.81μs (51.4% faster)


def test_large_invalid_tuple():
    # Tuple of 1000 ints should not be recognized
    codeflash_output = _is_single_color(
        tuple(range(1000))
    )  # 1.66μs -> 1.39μs (19.2% faster)


def test_large_list_with_mixed_types():
    # Large list with mixed types should not be recognized
    mixed_list = [0.1] * 999 + ["red"]
    codeflash_output = _is_single_color(mixed_list)  # 1.14μs -> 1.02μs (12.1% faster)


# --- DETERMINISM TEST ---


def test_determinism():
    # Running the same input multiple times should yield the same result
    for _ in range(10):
        codeflash_output = _is_single_color("red")  # 11.5μs -> 8.57μs (34.3% faster)
        codeflash_output = _is_single_color(["red", "blue"])
        codeflash_output = _is_single_color(
            (0.1, 0.2, 0.3)
        )  # 3.78μs -> 3.14μs (20.3% faster)
        codeflash_output = _is_single_color((0.1, 0.2))


# --- TYPE ROBUSTNESS TESTS ---


def test_tuple_of_strings():
    # Tuple of strings should not be recognized as single color
    codeflash_output = _is_single_color(
        ("red", "green", "blue")
    )  # 2.62μs -> 1.50μs (74.5% faster)


def test_tuple_of_mixed_types():
    # Tuple of mixed types should not be recognized
    codeflash_output = _is_single_color(
        (0.1, "red", 0.3)
    )  # 2.69μs -> 1.65μs (63.1% faster)


def test_nested_tuple():
    # Nested tuple should not be recognized
    codeflash_output = _is_single_color(
        ((0.1, 0.2, 0.3),)
    )  # 1.43μs -> 1.22μs (17.3% faster)


def test_nested_list():
    # Nested list should not be recognized
    codeflash_output = _is_single_color(
        [[0.1, 0.2, 0.3]]
    )  # 1.01μs -> 925ns (9.08% faster)


def test_tuple_with_list_inside():
    # Tuple containing a list should not be recognized
    codeflash_output = _is_single_color(
        ([0.1, 0.2, 0.3], 0.4, 0.5)
    )  # 2.69μs -> 1.72μs (56.6% faster)


def test_list_with_tuple_inside():
    # List containing a tuple should not be recognized
    codeflash_output = _is_single_color(
        [(0.1, 0.2, 0.3), 0.4, 0.5]
    )  # 2.38μs -> 1.36μs (75.8% faster)


# --- SPECIAL CASES ---


def test_unicode_color_string():
    # Unicode color string should be recognized
    codeflash_output = _is_single_color("red")  # 4.18μs -> 2.91μs (43.7% faster)


def test_uppercase_color_string():
    # Uppercase color string should be recognized if valid
    codeflash_output = _is_single_color("RED")  # 3.57μs -> 2.48μs (43.7% faster)
    codeflash_output = _is_single_color("GREEN")  # 1.35μs -> 907ns (48.7% faster)


def test_weird_but_valid_color_string():
    # Hex color string
    codeflash_output = _is_single_color("#FF0000")  # 3.07μs -> 2.27μs (35.1% faster)
    codeflash_output = _is_single_color("#00FF00")  # 1.21μs -> 881ns (37.5% faster)
    # 3-digit hex
    codeflash_output = _is_single_color("#F00")  # 915ns -> 631ns (45.0% faster)


def test_invalid_hex_color_string():
    # Invalid hex color string
    codeflash_output = _is_single_color("#GGGGGG")  # 14.8μs -> 13.0μs (14.2% faster)
    codeflash_output = _is_single_color("#FFFF")  # 1.39μs -> 1.01μs (37.5% faster)


def test_string_with_spaces():
    # String with spaces should not be recognized
    codeflash_output = _is_single_color("red blue")  # 12.6μs -> 10.7μs (17.4% faster)
    codeflash_output = _is_single_color(
        " firebrick "
    )  # 6.26μs -> 5.10μs (22.8% faster)


def test_string_with_special_characters():
    # String with special characters should not be recognized
    codeflash_output = _is_single_color("red!")  # 11.4μs -> 9.89μs (15.7% faster)
    codeflash_output = _is_single_color("blue@")  # 5.66μs -> 4.77μs (18.5% faster)


def test_string_with_numbers():
    # String with numbers should not be recognized unless valid
    codeflash_output = _is_single_color("red1")  # 11.6μs -> 9.70μs (19.3% faster)
    codeflash_output = _is_single_color("C10")  # 11.4μs -> 9.56μs (19.2% faster)


def test_string_with_newline():
    # String with newline should not be recognized
    codeflash_output = _is_single_color("red\n")  # 11.4μs -> 10.0μs (13.8% faster)


def test_string_with_tab():
    # String with tab should not be recognized
    codeflash_output = _is_single_color("red\t")  # 12.0μs -> 9.82μs (22.7% faster)


def test_string_with_leading_trailing_spaces():
    # Leading/trailing spaces should not be recognized
    codeflash_output = _is_single_color(" red")  # 12.1μs -> 10.0μs (20.3% faster)
    codeflash_output = _is_single_color("red ")  # 6.13μs -> 4.75μs (29.0% faster)


def test_empty_string():
    # Empty string should not be recognized
    codeflash_output = _is_single_color("")  # 11.0μs -> 9.23μs (19.2% faster)


def test_string_zero():
    # String "0" should not be recognized
    codeflash_output = _is_single_color("0")  # 3.04μs -> 2.18μs (39.4% faster)


def test_numeric_string():
    # Numeric string should not be recognized
    codeflash_output = _is_single_color("123")  # 12.6μs -> 10.7μs (17.2% faster)


def test_string_tuple_of_valid_length():
    # Tuple of 3 strings should not be recognized
    codeflash_output = _is_single_color(
        ("red", "green", "blue")
    )  # 3.08μs -> 1.78μs (73.3% faster)


def test_tuple_of_valid_length_with_invalid_types():
    # Tuple of 3 mixed types should not be recognized
    codeflash_output = _is_single_color(
        (0.1, "green", 0.3)
    )  # 2.82μs -> 1.77μs (59.6% faster)


def test_tuple_of_valid_length_with_none():
    # Tuple of 3 with None should not be recognized
    codeflash_output = _is_single_color(
        (0.1, None, 0.3)
    )  # 2.72μs -> 1.74μs (56.9% faster)


# codeflash_output is used to check that the output of the original code is the same as that of the optimized code.
from __future__ import annotations


# imports
from pandas.plotting._matplotlib.style import _is_single_color

# unit tests

# -------------------- BASIC TEST CASES --------------------


def test_named_color_string():
    # Basic named color
    codeflash_output = _is_single_color("red")  # 3.90μs -> 2.84μs (37.5% faster)
    # Alias
    codeflash_output = _is_single_color("g")  # 1.29μs -> 864ns (49.3% faster)
    # CSS4 color
    codeflash_output = _is_single_color("firebrick")  # 848ns -> 636ns (33.3% faster)
    # Matplotlib color cycle
    codeflash_output = _is_single_color("C0")  # 11.0μs -> 9.33μs (17.7% faster)


def test_rgb_tuple():
    # Tuple of 3 floats
    codeflash_output = _is_single_color(
        (0.1, 0.2, 0.3)
    )  # 2.89μs -> 1.97μs (46.6% faster)
    # Tuple of 3 ints
    codeflash_output = _is_single_color((1, 2, 3))  # 997ns -> 633ns (57.5% faster)


def test_rgba_tuple():
    # Tuple of 4 floats
    codeflash_output = _is_single_color(
        (0.1, 0.2, 0.3, 0.4)
    )  # 2.79μs -> 1.89μs (48.1% faster)
    # Tuple of 4 ints
    codeflash_output = _is_single_color((1, 2, 3, 4))  # 1.10μs -> 661ns (67.0% faster)


def test_invalid_string_color():
    # Invalid color string
    codeflash_output = _is_single_color("notacolor")  # 15.2μs -> 12.5μs (21.7% faster)
    # Empty string
    codeflash_output = _is_single_color("")  # 6.10μs -> 5.03μs (21.3% faster)


def test_non_color_type():
    # Integer
    codeflash_output = _is_single_color(42)  # 996ns -> 935ns (6.52% faster)
    # Float
    codeflash_output = _is_single_color(0.5)  # 332ns -> 299ns (11.0% faster)
    # None
    codeflash_output = _is_single_color(None)  # 272ns -> 209ns (30.1% faster)


# -------------------- EDGE TEST CASES --------------------


def test_sequence_of_colors():
    # List of named colors
    codeflash_output = _is_single_color(
        ["red", "blue"]
    )  # 1.06μs -> 847ns (25.4% faster)
    # Tuple of named colors
    codeflash_output = _is_single_color(
        ("red", "blue")
    )  # 1.04μs -> 893ns (16.6% faster)
    # List of float tuples
    codeflash_output = _is_single_color(
        [(0.1, 0.2, 0.3), (0.4, 0.5, 0.6)]
    )  # 399ns -> 327ns (22.0% faster)
    # Nested tuple (should not be interpreted as a single color)
    codeflash_output = _is_single_color(
        ((0.1, 0.2, 0.3),)
    )  # 410ns -> 332ns (23.5% faster)


def test_tuple_wrong_length():
    # Tuple of 2 floats
    codeflash_output = _is_single_color((0.1, 0.2))  # 1.44μs -> 1.21μs (18.7% faster)
    # Tuple of 5 floats
    codeflash_output = _is_single_color(
        (0.1, 0.2, 0.3, 0.4, 0.5)
    )  # 522ns -> 449ns (16.3% faster)
    # Tuple of 0 floats
    codeflash_output = _is_single_color(())  # 492ns -> 396ns (24.2% faster)


def test_tuple_with_non_numeric():
    # Tuple with a string
    codeflash_output = _is_single_color(
        (0.1, "red", 0.3)
    )  # 2.94μs -> 1.66μs (77.2% faster)
    # Tuple with None
    codeflash_output = _is_single_color(
        (0.1, None, 0.3)
    )  # 994ns -> 592ns (67.9% faster)
    # Tuple with bool
    codeflash_output = _is_single_color(
        (0.1, True, 0.3)
    )  # 1.13μs -> 669ns (69.4% faster)


def test_unusual_types():
    # Set of floats
    codeflash_output = _is_single_color(
        {0.1, 0.2, 0.3}
    )  # 2.71μs -> 1.79μs (51.3% faster)
    # Dict of floats
    codeflash_output = _is_single_color(
        {0: 0.1, 1: 0.2, 2: 0.3}
    )  # 1.26μs -> 758ns (66.2% faster)
    # Bytes
    codeflash_output = _is_single_color(b"red")  # 864ns -> 583ns (48.2% faster)


def test_single_element_tuple():
    # Tuple of one float
    codeflash_output = _is_single_color((0.1,))  # 1.32μs -> 1.18μs (12.2% faster)
    # Tuple of one string
    codeflash_output = _is_single_color(("red",))  # 521ns -> 442ns (17.9% faster)


def test_tuple_with_mixed_int_float():
    # Tuple with ints and floats
    codeflash_output = _is_single_color(
        (1, 0.2, 3.0)
    )  # 2.57μs -> 1.58μs (63.0% faster)
    codeflash_output = _is_single_color(
        (1, 0.2, 3.0, 0)
    )  # 1.26μs -> 775ns (63.0% faster)


def test_color_cycle_string():
    # Matplotlib color cycle strings
    for i in range(10):
        codeflash_output = _is_single_color(f"C{i}")  # 50.5μs -> 39.8μs (27.0% faster)


def test_case_sensitivity():
    # Lowercase and uppercase
    codeflash_output = _is_single_color("Red")  # 3.02μs -> 2.17μs (38.8% faster)
    codeflash_output = _is_single_color("RED")  # 1.15μs -> 879ns (31.3% faster)
    codeflash_output = _is_single_color("rEd")  # 900ns -> 632ns (42.4% faster)


# -------------------- LARGE SCALE TEST CASES --------------------


def test_large_rgb_tuple():
    # Very large tuple (should not be accepted)
    long_tuple = tuple([0.1] * 100)
    codeflash_output = _is_single_color(long_tuple)  # 1.81μs -> 1.60μs (13.0% faster)


def test_large_list_of_colors():
    # List of 1000 valid color strings (should not be accepted as single color)
    color_list = ["red"] * 1000
    codeflash_output = _is_single_color(color_list)  # 1.20μs -> 962ns (25.1% faster)


def test_large_list_of_rgb_tuples():
    # List of 1000 valid RGB tuples (should not be accepted as single color)
    rgb_list = [(0.1, 0.2, 0.3)] * 1000
    codeflash_output = _is_single_color(rgb_list)  # 1.15μs -> 972ns (18.7% faster)


def test_large_valid_color_string():
    # Long string that is not a color
    long_str = "a" * 1000
    codeflash_output = _is_single_color(long_str)  # 21.0μs -> 17.3μs (21.3% faster)


def test_large_valid_color_tuple():
    # Tuple of 4 ints at upper bound
    codeflash_output = _is_single_color(
        (255, 255, 255, 255)
    )  # 2.96μs -> 1.78μs (65.7% faster)


def test_large_scale_performance():
    # Check performance for a valid color string among many invalids
    color_list = ["notacolor"] * 999 + ["red"]
    codeflash_output = _is_single_color(color_list)  # 1.20μs -> 978ns (22.7% faster)


# -------------------- MISCELLANEOUS CASES --------------------


def test_bool_and_none_in_tuple():
    # Tuple of bools
    codeflash_output = _is_single_color(
        (True, False, True)
    )  # 2.81μs -> 1.74μs (61.8% faster)
    # Tuple with None
    codeflash_output = _is_single_color(
        (None, None, None)
    )  # 1.51μs -> 710ns (112% faster)


def test_list_of_single_color():
    # List with a single valid color string
    codeflash_output = _is_single_color(["red"])  # 1.72μs -> 1.53μs (12.2% faster)
    # List with a single valid RGB tuple
    codeflash_output = _is_single_color(
        [(0.1, 0.2, 0.3)]
    )  # 408ns -> 362ns (12.7% faster)


def test_tuple_with_non_numeric_types():
    # Tuple of objects
    codeflash_output = _is_single_color(
        (object(), object(), object())
    )  # 3.12μs -> 1.88μs (65.7% faster)


def test_tuple_with_nan_inf():
    # Tuple with nan and inf
    import math

    codeflash_output = _is_single_color(
        (math.nan, 0.2, 0.3)
    )  # 2.81μs -> 1.75μs (60.5% faster)
    codeflash_output = _is_single_color(
        (math.inf, 0.2, 0.3)
    )  # 966ns -> 595ns (62.4% faster)


def test_tuple_with_negative_values():
    # Negative values are allowed
    codeflash_output = _is_single_color((-1, -2, -3))  # 2.46μs -> 1.57μs (56.7% faster)
    codeflash_output = _is_single_color(
        (-1.0, -2.0, -3.0, -4.0)
    )  # 1.29μs -> 901ns (43.5% faster)


def test_tuple_with_large_values():
    # Large numbers
    codeflash_output = _is_single_color(
        (1e6, 2e6, 3e6)
    )  # 2.40μs -> 1.58μs (51.9% faster)


def test_tuple_with_zero_values():
    # All zero
    codeflash_output = _is_single_color((0, 0, 0))  # 2.37μs -> 1.58μs (49.5% faster)
    codeflash_output = _is_single_color((0, 0, 0, 0))  # 1.19μs -> 714ns (67.2% faster)


# codeflash_output is used to check that the output of the original code is the same as that of the optimized code.

To edit these changes git checkout codeflash/optimize-_is_single_color-mir1yojh and push.

Codeflash Static Badge

The optimized code achieves a 30% speedup through two key optimizations:

**1. ColorConverter instance caching:** The original code created a new `matplotlib.colors.ColorConverter()` instance on every call to `_is_single_string_color`. The optimized version caches this instance as a module-level variable `_conv`. This eliminates repeated object instantiation overhead, which the profiler shows reduced time from 43,939ns to 15,090ns per call in `_is_single_string_color`.

**2. More efficient validation in `_is_floats_color`:** The original version used a chained boolean expression with `all()` which creates a generator and evaluates all elements even when early failures occur. The optimized version restructures the logic with early returns:
- Checks `is_list_like(color)` first and returns `False` immediately for non-sequences
- Validates length (`n != 3 and n != 4`) before any iteration
- Uses an explicit `for` loop with early return instead of `all()`, avoiding generator overhead

The profiler shows this reduced `_is_floats_color` execution time from 522,257ns to 358,781ns total.

**Impact on workloads:** The function references show `_is_single_color` is called from `_get_colors_from_color` and `_gen_list_of_colors_from_iterable`, indicating it's in a hot path for color processing in matplotlib plotting. The test results show particularly strong improvements (50-70% faster) for RGB/RGBA tuple validation, which are common in plotting workflows. The optimizations are most beneficial when processing many color inputs or when `_is_single_string_color` is called frequently, making this especially valuable for plotting operations that handle multiple colors or are called repeatedly.
@codeflash-ai codeflash-ai bot requested a review from mashraf-222 December 4, 2025 06:26
@codeflash-ai codeflash-ai bot added ⚡️ codeflash Optimization PR opened by Codeflash AI 🎯 Quality: High Optimization Quality according to Codeflash labels Dec 4, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

⚡️ codeflash Optimization PR opened by Codeflash AI 🎯 Quality: High Optimization Quality according to Codeflash

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant