Skip to content

Conversation

@codeflash-ai
Copy link

@codeflash-ai codeflash-ai bot commented Oct 28, 2025

📄 6% (0.06x) speedup for _is_visual in src/bokeh/plotting/_renderer.py

⏱️ Runtime : 1.41 milliseconds 1.33 milliseconds (best of 138 runs)

📝 Explanation and details

Correctness verification report:

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

# imports
import pytest  # used for our unit tests
from bokeh.plotting._renderer import _is_visual

#-----------------------------------------------------------------------------
# Code
#-----------------------------------------------------------------------------

# unit tests

# ---------------------------
# Basic Test Cases
# ---------------------------

def test_basic_visual_true_cases():
    # Test with known visual features and valid traits
    codeflash_output = _is_visual("line_color") # 1.24μs -> 1.20μs (3.50% faster)
    codeflash_output = _is_visual("fill_alpha") # 489ns -> 422ns (15.9% faster)
    codeflash_output = _is_visual("hatch_pattern") # 434ns -> 429ns (1.17% faster)
    codeflash_output = _is_visual("text_font") # 360ns -> 299ns (20.4% faster)
    codeflash_output = _is_visual("global_alpha") # 379ns -> 372ns (1.88% faster)

def test_basic_visual_false_cases():
    # Test with non-visual features
    codeflash_output = _is_visual("foo_bar") # 1.10μs -> 986ns (11.7% faster)
    codeflash_output = _is_visual("data_source") # 577ns -> 481ns (20.0% faster)
    codeflash_output = _is_visual("legend_label") # 439ns -> 375ns (17.1% faster)
    codeflash_output = _is_visual("x_axis") # 405ns -> 414ns (2.17% slower)

def test_basic_trait_none_cases():
    # Test with visual feature but missing trait (no '_')
    codeflash_output = _is_visual("line") # 1.09μs -> 723ns (50.2% faster)
    codeflash_output = _is_visual("fill") # 359ns -> 276ns (30.1% faster)
    codeflash_output = _is_visual("hatch") # 382ns -> 267ns (43.1% faster)
    codeflash_output = _is_visual("text") # 293ns -> 227ns (29.1% faster)
    codeflash_output = _is_visual("global") # 337ns -> 240ns (40.4% faster)

# ---------------------------
# Edge Test Cases
# ---------------------------

@pytest.mark.parametrize("input_str", [
    "",  # empty string
    "_",  # just underscore
    "____",  # multiple underscores but no feature/trait
    "line_",  # underscore but no trait
    "line__",  # double underscore after feature
    "line_color_extra",  # more than one underscore
    "linecolor",  # visual feature embedded, but not separated
    "Line_color",  # case sensitivity test
    "line_Color",  # case sensitivity test
    "line_",  # trait is empty string
    "l_color",  # single char feature
    "line_",  # feature with underscore, trait empty
])
def test_edge_cases(input_str):
    # Only 'line_color' should return True, others should be False
    # These are all edge cases and should return False
    codeflash_output = _is_visual(input_str) # 12.4μs -> 11.8μs (5.26% faster)

def test_non_string_input():
    # Should raise AttributeError if input is not a string
    with pytest.raises(AttributeError):
        _is_visual(None) # 1.33μs -> 1.25μs (5.82% faster)
    with pytest.raises(AttributeError):
        _is_visual(123) # 887ns -> 710ns (24.9% faster)
    with pytest.raises(AttributeError):
        _is_visual(["line_color"]) # 658ns -> 544ns (21.0% faster)
    with pytest.raises(AttributeError):
        _is_visual({"ft": "line_color"}) # 595ns -> 468ns (27.1% faster)

# ---------------------------
# Large Scale Test Cases
# ---------------------------

def test_large_scale_visual_true():
    # Generate many valid visual feature-trait pairs
    features = ['line', 'fill', 'hatch', 'text', 'global']
    traits = [f"trait{i}" for i in range(100)]
    for feature in features:
        for trait in traits:
            name = f"{feature}_{trait}"
            codeflash_output = _is_visual(name)  # All should be visual

def test_large_scale_visual_false():
    # Generate many non-visual feature-trait pairs
    non_visual_features = ['foo', 'bar', 'baz', 'data', 'legend', 'x', 'y', 'tick', 'axis']
    traits = [f"trait{i}" for i in range(100)]
    for feature in non_visual_features:
        for trait in traits:
            name = f"{feature}_{trait}"
            codeflash_output = _is_visual(name)  # None should be visual

def test_large_scale_missing_trait():
    # Generate many visual features without trait
    features = ['line', 'fill', 'hatch', 'text', 'global']
    for feature in features:
        codeflash_output = _is_visual(feature) # 2.71μs -> 2.03μs (33.7% faster)

def test_large_scale_random_strings():
    # Generate random strings that should not be visual
    import random
    import string
    for _ in range(200):
        s = ''.join(random.choices(string.ascii_letters + string.digits + "_", k=random.randint(1, 20)))
        # Only if it matches the pattern 'feature_trait' with feature in allowed list, it's visual
        parts = s.split("_", 1)
        if len(parts) == 2 and parts[0] in ('line', 'fill', 'hatch', 'text', 'global') and parts[1]:
            continue  # skip, would be visual
        codeflash_output = _is_visual(s) # 62.7μs -> 52.1μs (20.3% faster)

# ---------------------------
# Determinism & Mutation Safety
# ---------------------------

def test_mutation_safety():
    # Changing the feature or trait should affect the result
    codeflash_output = _is_visual("line_color") # 1.06μs -> 1.14μs (6.67% slower)
    codeflash_output = _is_visual("line_colour") # 450ns -> 430ns (4.65% faster)
    codeflash_output = _is_visual("li_color") # 452ns -> 409ns (10.5% faster)
    codeflash_output = _is_visual("linecolor") # 492ns -> 351ns (40.2% faster)
    codeflash_output = _is_visual("line_") # 364ns -> 405ns (10.1% slower)

# ---------------------------
# Additional Edge Cases
# ---------------------------

def test_leading_trailing_underscores():
    # Leading or trailing underscores should not match
    codeflash_output = _is_visual("_line_color") # 953ns -> 889ns (7.20% faster)
    codeflash_output = _is_visual("line_color_") # 576ns -> 632ns (8.86% slower)
    codeflash_output = _is_visual("_fill_alpha") # 353ns -> 358ns (1.40% slower)
    codeflash_output = _is_visual("fill_alpha_") # 376ns -> 327ns (15.0% faster)

def test_multiple_underscores():
    # Only the first underscore is considered
    codeflash_output = _is_visual("line_color_alpha") # 984ns -> 997ns (1.30% slower)
    codeflash_output = _is_visual("fill_alpha_beta") # 495ns -> 458ns (8.08% faster)
    codeflash_output = _is_visual("text_font_size") # 385ns -> 322ns (19.6% faster)
    codeflash_output = _is_visual("foo_bar_baz") # 425ns -> 387ns (9.82% faster)

def test_case_sensitivity():
    # Features must be lowercase and exact
    codeflash_output = _is_visual("Line_color") # 1.02μs -> 819ns (24.1% faster)
    codeflash_output = _is_visual("LINE_color") # 399ns -> 390ns (2.31% faster)
    codeflash_output = _is_visual("line_Color") # 388ns -> 408ns (4.90% slower)
    codeflash_output = _is_visual("line_color") # 295ns -> 301ns (1.99% slower)

def test_trait_none_for_non_visual_feature():
    # Non-visual feature with no trait
    codeflash_output = _is_visual("foo") # 1.07μs -> 743ns (44.4% faster)
    codeflash_output = _is_visual("bar") # 422ns -> 434ns (2.76% slower)
    codeflash_output = _is_visual("baz") # 292ns -> 227ns (28.6% 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
import pytest  # used for our unit tests
from bokeh.plotting._renderer import _is_visual

#-----------------------------------------------------------------------------
# Code
#-----------------------------------------------------------------------------

# unit tests

# 1. Basic Test Cases

def test_basic_line_color():
    # line_color should be visual
    codeflash_output = _is_visual("line_color") # 962ns -> 995ns (3.32% slower)

def test_basic_fill_alpha():
    # fill_alpha should be visual
    codeflash_output = _is_visual("fill_alpha") # 1.00μs -> 873ns (14.5% faster)

def test_basic_hatch_pattern():
    # hatch_pattern should be visual
    codeflash_output = _is_visual("hatch_pattern") # 1.14μs -> 1.08μs (5.64% faster)

def test_basic_text_font_size():
    # text_font_size should be visual
    codeflash_output = _is_visual("text_font_size") # 1.12μs -> 978ns (14.7% faster)

def test_basic_global_alpha():
    # global_alpha should be visual
    codeflash_output = _is_visual("global_alpha") # 1.07μs -> 1.06μs (1.42% faster)

def test_basic_non_visual_feature():
    # foo_bar is not a visual feature
    codeflash_output = _is_visual("foo_bar") # 1.06μs -> 989ns (7.08% faster)

def test_basic_single_word():
    # 'line' alone is not visual, needs a trait
    codeflash_output = _is_visual("line") # 1.09μs -> 759ns (43.6% faster)


def test_edge_no_underscore():
    # no underscore, should not be visual
    codeflash_output = _is_visual("linecolor") # 1.40μs -> 976ns (42.9% faster)

def test_edge_underscore_at_start():
    # underscore at start, feature is empty string, not visual
    codeflash_output = _is_visual("_color") # 1.23μs -> 1.10μs (11.2% faster)

def test_edge_underscore_at_end():
    # underscore at end, trait is empty, should be visual because trait is not None
    # But per _split_feature_trait, 'line_' -> ('line', '') so trait is ''
    # '' is not None, so should be visual if feature is in the set
    codeflash_output = _is_visual("line_") # 1.17μs -> 1.15μs (1.30% faster)

def test_edge_multiple_underscores():
    # only first underscore matters: 'fill_color_alpha' -> ('fill', 'color_alpha')
    codeflash_output = _is_visual("fill_color_alpha") # 1.24μs -> 1.23μs (0.162% faster)

def test_edge_one_letter_feature():
    # 'l_color' -> feature 'l', not in the set
    codeflash_output = _is_visual("l_color") # 1.13μs -> 973ns (16.4% faster)

def test_edge_one_letter_trait():
    # 'line_c' -> feature 'line', trait 'c', should be visual
    codeflash_output = _is_visual("line_c") # 1.11μs -> 1.10μs (1.00% faster)

def test_edge_empty_trait():
    # 'fill_' -> feature 'fill', trait '', should be visual
    codeflash_output = _is_visual("fill_") # 1.14μs -> 1.08μs (5.48% faster)

def test_edge_non_visual_feature_with_trait():
    # 'foo_bar' -> feature 'foo', not in set
    codeflash_output = _is_visual("foo_bar") # 1.15μs -> 1.08μs (6.57% faster)

def test_edge_case_sensitive():
    # 'Line_color' -> feature 'Line', not in set (case matters)
    codeflash_output = _is_visual("Line_color") # 1.18μs -> 947ns (24.1% faster)

def test_edge_numeric_trait():
    # 'line_1' -> feature 'line', trait '1', should be visual
    codeflash_output = _is_visual("line_1") # 1.06μs -> 1.11μs (4.41% slower)

def test_edge_numeric_feature():
    # '1_color' -> feature '1', not in set
    codeflash_output = _is_visual("1_color") # 1.04μs -> 944ns (10.5% faster)

def test_edge_feature_one_char():
    # 'l_' -> feature 'l', not in set
    codeflash_output = _is_visual("l_") # 1.00μs -> 874ns (14.9% faster)

def test_edge_only_underscore():
    # '_' -> feature '', trait '', not in set
    codeflash_output = _is_visual("_") # 1.02μs -> 908ns (12.8% faster)

def test_edge_double_underscore():
    # 'line__color' -> feature 'line', trait '_color', should be visual
    codeflash_output = _is_visual("line__color") # 1.03μs -> 1.06μs (3.48% slower)

def test_edge_long_trait():
    # 'text_super_long_trait_name_with_underscores' -> ('text', 'super_long_trait_name_with_underscores')
    codeflash_output = _is_visual("text_super_long_trait_name_with_underscores") # 1.09μs -> 1.11μs (1.89% slower)

def test_edge_unicode_feature():
    # 'líne_color' (with accent) is not in set
    codeflash_output = _is_visual("líne_color") # 1.38μs -> 1.29μs (7.13% faster)

def test_edge_unicode_trait():
    # 'line_colôr' (with accent in trait) is visual
    codeflash_output = _is_visual("line_colôr") # 1.19μs -> 1.31μs (9.01% slower)

# 3. Large Scale Test Cases

def test_large_scale_all_visual_features():
    # Test all valid features with 1000 different traits
    features = ['line', 'fill', 'hatch', 'text', 'global']
    for feature in features:
        for i in range(200):  # 5*200 = 1000 cases
            trait = f"trait_{i}"
            s = f"{feature}_{trait}"
            codeflash_output = _is_visual(s)

def test_large_scale_non_visual_features():
    # Test 1000 non-visual features with valid trait
    for i in range(1000):
        s = f"foo{i}_bar"
        codeflash_output = _is_visual(s) # 292μs -> 275μs (6.28% faster)

def test_large_scale_visual_and_nonvisual_mixed():
    # Mix of visual and non-visual features
    for i in range(500):
        # Visual
        s1 = f"line_trait{i}"
        codeflash_output = _is_visual(s1) # 141μs -> 142μs (0.736% slower)
        # Non-visual
        s2 = f"notvisual_trait{i}"
        codeflash_output = _is_visual(s2)

def test_large_scale_long_strings():
    # Visual feature with very long trait
    long_trait = "x" * 900
    codeflash_output = _is_visual(f"fill_{long_trait}") # 1.42μs -> 1.51μs (6.03% slower)
    # Non-visual feature with very long trait
    codeflash_output = _is_visual(f"foo_{long_trait}") # 645ns -> 591ns (9.14% faster)


#------------------------------------------------
from bokeh.plotting._renderer import _is_visual

def test__is_visual():
    _is_visual('fill_')
🔎 Concolic Coverage Tests and Runtime
Test File::Test Function Original ⏱️ Optimized ⏱️ Speedup
codeflash_concolic_cthbg6_3/tmp76eagmko/test_concolic_coverage.py::test__is_visual 1.49μs 1.46μs 2.33%✅

To edit these changes git checkout codeflash/optimize-_is_visual-mhb6c6t6 and push.

Codeflash

@codeflash-ai codeflash-ai bot requested a review from mashraf-222 October 28, 2025 23:04
@codeflash-ai codeflash-ai bot added the ⚡️ codeflash Optimization PR opened by Codeflash AI label Oct 28, 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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant