Skip to content

Conversation

@codeflash-ai
Copy link

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

📄 200% (2.00x) speedup for _parse_latex_cell_styles in pandas/io/formats/style_render.py

⏱️ Runtime : 17.3 milliseconds 5.78 milliseconds (best of 100 runs)

📝 Explanation and details

The optimization achieves a 199% speedup by eliminating redundant operations and reducing object allocations in the core processing loop of _parse_latex_cell_styles.

Key optimizations:

  1. Eliminated formatter dictionary creation: The original code created a 5-element dictionary on every iteration (9,095 times), causing significant overhead. The optimized version uses direct conditional branches instead, reducing allocation and lookup costs.

  2. Reduced string conversions: str(options) was called multiple times per iteration. Now it's computed once and stored as options_str, eliminating redundant conversions.

  3. Precompiled regex patterns: Moved regex compilation outside the color function to avoid recompiling patterns on each CSS color conversion, improving RGB/RGBA parsing performance.

  4. Optimized wrap argument handling: Extracted _WRAP_ARGS as a module-level constant and converted to tuple for membership tests, reducing list recreation overhead.

  5. Simplified list operations: Replaced .extend([single_item]) with .append(single_item) to avoid unnecessary list wrapping.

Performance impact by test type:

  • Basic LaTeX styling (no CSS conversion): 40-90% faster due to eliminated formatter dictionary creation
  • Large-scale operations (1000+ styles): 200-400% faster, showing excellent scalability
  • CSS conversion cases: Mixed results - simple conversions are slightly slower due to tuple conversion overhead, but complex RGB/RGBA parsing is 8-12% faster due to precompiled regex

The function is called from _parse_latex_header_span for table cell formatting in pandas styling, making this optimization beneficial for LaTeX export performance, especially with complex styled DataFrames containing many cells.

Correctness verification report:

Test Status
⚙️ Existing Unit Tests 58 Passed
🌀 Generated Regression Tests 102 Passed
⏪ Replay Tests 🔘 None Found
🔎 Concolic Coverage Tests 🔘 None Found
📊 Tests Coverage 100.0%
⚙️ Existing Unit Tests and Runtime
Test File::Test Function Original ⏱️ Optimized ⏱️ Speedup
io/formats/style/test_to_latex.py::test_parse_latex_cell_styles_basic 7.11μs 4.90μs 45.0%✅
io/formats/style/test_to_latex.py::test_parse_latex_cell_styles_braces 23.2μs 17.2μs 35.4%✅
🌀 Generated Regression Tests and Runtime
from __future__ import annotations

from typing import Union

# imports
from pandas.io.formats.style_render import _parse_latex_cell_styles

CSSPair = tuple[str, Union[str, float]]
CSSList = list[CSSPair]

# unit tests

# 1. Basic Test Cases


def test_single_simple_command():
    # Basic: single style, no special flags
    styles = [("textbf", "")]
    codeflash_output = _parse_latex_cell_styles(styles, "foo")
    result = codeflash_output  # 2.81μs -> 1.51μs (85.5% faster)


def test_single_command_with_options():
    # Basic: single style with options
    styles = [("textcolor", "{red}")]
    codeflash_output = _parse_latex_cell_styles(styles, "bar")
    result = codeflash_output  # 2.71μs -> 1.51μs (79.5% faster)


def test_multiple_commands_nesting():
    # Basic: multiple styles, nesting order
    styles = [("textbf", ""), ("textcolor", "{blue}")]
    codeflash_output = _parse_latex_cell_styles(styles, "baz")
    result = codeflash_output  # 4.02μs -> 2.07μs (94.2% faster)


def test_multiple_commands_with_flags():
    # Basic: with --wrap flag
    styles = [("textbf", "--wrap"), ("textcolor", "{red}")]
    codeflash_output = _parse_latex_cell_styles(styles, "baz")
    result = codeflash_output  # 5.34μs -> 3.19μs (67.5% faster)


def test_no_styles():
    # Basic: empty styles list returns display_value unchanged
    codeflash_output = _parse_latex_cell_styles([], "hello")
    result = codeflash_output  # 751ns -> 657ns (14.3% faster)


def test_command_with_wrap_flag_and_options():
    # Basic: --wrap with options
    styles = [("textcolor", "{red}--wrap")]
    codeflash_output = _parse_latex_cell_styles(styles, "foo")
    result = codeflash_output  # 4.28μs -> 2.98μs (43.9% faster)


def test_command_with_rwrap_flag():
    # Basic: --rwrap flag
    styles = [("textbf", "--rwrap")]
    codeflash_output = _parse_latex_cell_styles(styles, "foo")
    result = codeflash_output  # 4.00μs -> 2.75μs (45.4% faster)


def test_command_with_lwrap_flag():
    # Basic: --lwrap flag
    styles = [("textbf", "--lwrap")]
    codeflash_output = _parse_latex_cell_styles(styles, "foo")
    result = codeflash_output  # 3.84μs -> 2.67μs (43.7% faster)


def test_command_with_dwrap_flag():
    # Basic: --dwrap flag
    styles = [("textbf", "--dwrap")]
    codeflash_output = _parse_latex_cell_styles(styles, "foo")
    result = codeflash_output  # 3.72μs -> 2.74μs (35.8% faster)


def test_command_with_flag_and_comment():
    # Basic: flag with CSS comment
    styles = [("textbf", "--wrap /* comment */")]
    codeflash_output = _parse_latex_cell_styles(styles, "foo")
    result = codeflash_output  # 4.49μs -> 3.27μs (37.3% faster)


# 2. Edge Test Cases


def test_style_with_empty_option():
    # Edge: empty string as option
    styles = [("textbf", "")]
    codeflash_output = _parse_latex_cell_styles(styles, "")
    result = codeflash_output  # 2.59μs -> 1.51μs (71.7% faster)


def test_style_with_whitespace_option():
    # Edge: whitespace in option
    styles = [("textbf", "   ")]
    codeflash_output = _parse_latex_cell_styles(styles, "foo")
    result = codeflash_output  # 2.60μs -> 1.48μs (75.8% faster)


def test_flag_in_middle_of_option():
    # Edge: flag appears in middle of option string
    styles = [("textbf", "abc--wrapdef")]
    codeflash_output = _parse_latex_cell_styles(styles, "foo")
    result = codeflash_output  # 4.43μs -> 3.04μs (46.1% faster)


def test_unknown_flag_in_option():
    # Edge: unknown flag in option string, should ignore
    styles = [("textbf", "abc--unknown")]
    codeflash_output = _parse_latex_cell_styles(styles, "foo")
    result = codeflash_output  # 2.64μs -> 1.60μs (64.6% faster)


def test_style_with_non_string_option():
    # Edge: option is a float
    styles = [("fontsize", 12.0)]
    codeflash_output = _parse_latex_cell_styles(styles, "foo")
    result = codeflash_output  # 4.37μs -> 2.86μs (52.9% faster)


def test_style_with_special_characters():
    # Edge: option contains LaTeX special chars
    styles = [("textcolor", "{red%}--wrap")]
    codeflash_output = _parse_latex_cell_styles(styles, "foo")
    result = codeflash_output  # 4.29μs -> 2.97μs (44.4% faster)


def test_multiple_flags_in_option():
    # Edge: multiple flags in option string, only first one used
    styles = [("textbf", "--wrap--rwrap")]
    codeflash_output = _parse_latex_cell_styles(styles, "foo")
    result = codeflash_output  # 4.11μs -> 2.77μs (48.7% faster)


def test_flag_with_leading_trailing_spaces():
    # Edge: flag with leading/trailing spaces
    styles = [("textbf", "   --wrap   ")]
    codeflash_output = _parse_latex_cell_styles(styles, "foo")
    result = codeflash_output  # 3.94μs -> 2.77μs (41.8% faster)


def test_flag_with_css_comment_and_spaces():
    # Edge: flag with CSS comment and spaces
    styles = [("textbf", "   --wrap /* comment */   ")]
    codeflash_output = _parse_latex_cell_styles(styles, "foo")
    result = codeflash_output  # 4.43μs -> 3.37μs (31.6% faster)


def test_flag_with_multiple_css_comments():
    # Edge: multiple CSS comments
    styles = [("textbf", "   --wrap /* comment */ /* another */   ")]
    codeflash_output = _parse_latex_cell_styles(styles, "foo")
    result = codeflash_output  # 4.69μs -> 3.35μs (39.9% faster)


def test_convert_css_font_weight():
    # Edge: convert_css flag with font-weight
    styles = [("font-weight", "bold")]
    codeflash_output = _parse_latex_cell_styles(styles, "foo", convert_css=True)
    result = codeflash_output  # 6.07μs -> 7.24μs (16.2% slower)


def test_convert_css_font_style():
    # Edge: convert_css flag with font-style
    styles = [("font-style", "italic")]
    codeflash_output = _parse_latex_cell_styles(styles, "foo", convert_css=True)
    result = codeflash_output  # 5.81μs -> 6.55μs (11.4% slower)


def test_convert_css_color_string():
    # Edge: convert_css with color string
    styles = [("color", "red")]
    codeflash_output = _parse_latex_cell_styles(styles, "foo", convert_css=True)
    result = codeflash_output  # 6.82μs -> 7.70μs (11.4% slower)


def test_convert_css_color_hex():
    # Edge: convert_css with color hex
    styles = [("color", "#ff00cc")]
    codeflash_output = _parse_latex_cell_styles(styles, "foo", convert_css=True)
    result = codeflash_output  # 7.25μs -> 8.14μs (11.0% slower)


def test_convert_css_color_short_hex():
    # Edge: convert_css with color short hex
    styles = [("color", "#f0c")]
    codeflash_output = _parse_latex_cell_styles(styles, "foo", convert_css=True)
    result = codeflash_output  # 7.87μs -> 8.66μs (9.18% slower)


def test_convert_css_color_rgb():
    # Edge: convert_css with rgb
    styles = [("color", "rgb(128, 255, 0)")]
    codeflash_output = _parse_latex_cell_styles(styles, "foo", convert_css=True)
    result = codeflash_output  # 17.3μs -> 16.0μs (8.14% faster)


def test_convert_css_color_rgba():
    # Edge: convert_css with rgba
    styles = [("color", "rgba(128, 255, 0, 0.5)")]
    codeflash_output = _parse_latex_cell_styles(styles, "foo", convert_css=True)
    result = codeflash_output  # 15.7μs -> 14.1μs (11.4% faster)


def test_convert_css_background_color():
    # Edge: convert_css with background-color (should use cellcolor and --lwrap)
    styles = [("background-color", "red")]
    codeflash_output = _parse_latex_cell_styles(styles, "foo", convert_css=True)
    result = codeflash_output  # 8.53μs -> 9.07μs (5.93% slower)


def test_convert_css_with_flag():
    # Edge: convert_css with style containing latex flag
    styles = [("font-weight", "bold--wrap")]
    codeflash_output = _parse_latex_cell_styles(styles, "foo", convert_css=True)
    result = codeflash_output  # 7.52μs -> 8.26μs (8.95% slower)


def test_convert_css_with_latex_tag():
    # Edge: convert_css with --latex tag (should not convert)
    styles = [("textbf", "--latex")]
    codeflash_output = _parse_latex_cell_styles(styles, "foo", convert_css=True)
    result = codeflash_output  # 5.10μs -> 5.84μs (12.6% slower)


def test_convert_css_with_unknown_attribute():
    # Edge: convert_css with unknown attribute (should skip)
    styles = [("unknown", "value")]
    codeflash_output = _parse_latex_cell_styles(styles, "foo", convert_css=True)
    result = codeflash_output  # 2.96μs -> 4.66μs (36.6% slower)


def test_convert_css_multiple_styles():
    # Edge: convert_css with multiple styles
    styles = [("font-weight", "bold"), ("color", "red")]
    codeflash_output = _parse_latex_cell_styles(styles, "foo", convert_css=True)
    result = codeflash_output  # 8.78μs -> 9.02μs (2.63% slower)


def test_convert_css_multiple_flags():
    # Edge: convert_css with multiple flags
    styles = [("font-weight", "bold--wrap"), ("color", "red--wrap")]
    codeflash_output = _parse_latex_cell_styles(styles, "foo", convert_css=True)
    result = codeflash_output  # 12.0μs -> 12.2μs (1.38% slower)


def test_convert_css_flag_and_comment():
    # Edge: convert_css with flag and CSS comment
    styles = [("font-weight", "bold--wrap /* comment */")]
    codeflash_output = _parse_latex_cell_styles(styles, "foo", convert_css=True)
    result = codeflash_output  # 4.93μs -> 7.03μs (29.8% slower)


def test_convert_css_with_mixed_flags_and_comments():
    # Edge: convert_css with mixed flags and comments
    styles = [
        ("font-weight", "bold--wrap /* comment */"),
        ("color", "red--wrap /* c */"),
    ]
    codeflash_output = _parse_latex_cell_styles(styles, "foo", convert_css=True)
    result = codeflash_output  # 10.7μs -> 11.5μs (6.76% slower)


def test_convert_css_with_non_string_value():
    # Edge: convert_css with non-string value (should skip conversion)
    styles = [("font-weight", 700)]
    codeflash_output = _parse_latex_cell_styles(styles, "foo", convert_css=True)
    result = codeflash_output  # 4.06μs -> 5.61μs (27.7% slower)


# 3. Large Scale Test Cases


def test_large_number_of_styles():
    # Large: 100 styles, all simple, should nest correctly
    styles = [("cmd" + str(i), "") for i in range(100)]
    codeflash_output = _parse_latex_cell_styles(styles, "foo")
    result = codeflash_output  # 81.0μs -> 24.5μs (230% faster)
    # The outermost command should wrap the rest
    expected = "foo"
    for i in reversed(range(100)):
        expected = f"\\cmd{i} {expected}"


def test_large_number_of_styles_with_wrap():
    # Large: 100 styles, all with --wrap, should nest with curly braces
    styles = [("cmd" + str(i), "--wrap") for i in range(100)]
    codeflash_output = _parse_latex_cell_styles(styles, "foo")
    result = codeflash_output  # 104μs -> 41.1μs (155% faster)
    # The outermost command should wrap the rest in curly braces
    expected = "foo"
    for i in reversed(range(100)):
        expected = f"{{\\cmd{i} {expected}}}"


def test_large_number_of_styles_with_mixed_flags():
    # Large: 100 styles, alternating --wrap and --rwrap
    styles = [
        ("cmd" + str(i), "--wrap" if i % 2 == 0 else "--rwrap") for i in range(100)
    ]
    codeflash_output = _parse_latex_cell_styles(styles, "foo")
    result = codeflash_output  # 106μs -> 46.3μs (130% faster)
    expected = "foo"
    for i in reversed(range(100)):
        if i % 2 == 0:
            expected = f"{{\\cmd{i} {expected}}}"
        else:
            expected = f"\\cmd{i}{{{expected}}}"


def test_large_scale_convert_css():
    # Large: 500 font-weight styles with convert_css
    styles = [("font-weight", "bold")] * 500
    codeflash_output = _parse_latex_cell_styles(styles, "foo", convert_css=True)
    result = codeflash_output  # 651μs -> 251μs (159% faster)
    expected = "foo"
    for _ in range(500):
        expected = r"\bfseries " + expected


def test_large_scale_convert_css_with_wrap():
    # Large: 500 font-weight styles with --wrap and convert_css
    styles = [("font-weight", "bold--wrap")] * 500
    codeflash_output = _parse_latex_cell_styles(styles, "foo", convert_css=True)
    result = codeflash_output  # 1.22ms -> 447μs (174% faster)
    expected = "foo"
    for _ in range(500):
        expected = r"{\bfseries " + expected + "}"


def test_large_scale_mixed_styles_convert_css():
    # Large: 100 font-weight and 100 color styles, alternating, with convert_css
    styles = []
    for i in range(100):
        styles.append(("font-weight", "bold"))
        styles.append(("color", "red"))
    codeflash_output = _parse_latex_cell_styles(styles, "foo", convert_css=True)
    result = codeflash_output  # 282μs -> 135μs (108% faster)
    expected = "foo"
    for i in reversed(range(200)):
        if i % 2 == 0:
            expected = (
                r"\fontweight" + " " + expected if False else r"\bfseries " + expected
            )
        else:
            expected = r"\color{red} " + expected
    # Since font-weight always converts to \bfseries
    # So for even i: \bfseries, odd i: \color{red}
    expected = "foo"
    for i in reversed(range(200)):
        if i % 2 == 0:
            expected = r"\bfseries " + expected
        else:
            expected = r"\color{red} " + expected


def test_large_scale_no_styles():
    # Large: display_value only, no styles
    codeflash_output = _parse_latex_cell_styles([], "foo" * 1000)
    result = codeflash_output  # 755ns -> 613ns (23.2% 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

from typing import Union

# imports
from pandas.io.formats.style_render import _parse_latex_cell_styles

CSSPair = tuple[str, Union[str, float]]
CSSList = list[CSSPair]

# unit tests

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


def test_empty_styles_returns_display_value():
    # No styles, should return display_value unchanged
    codeflash_output = _parse_latex_cell_styles(
        [], "foo"
    )  # 887ns -> 668ns (32.8% faster)


def test_single_style_basic_command():
    # Single style, no flags
    codeflash_output = _parse_latex_cell_styles(
        [("bfseries", "")], "bar"
    )  # 2.88μs -> 1.57μs (83.0% faster)


def test_single_style_with_option():
    # Single style, with option
    codeflash_output = _parse_latex_cell_styles(
        [("textcolor", "{red}")], "baz"
    )  # 2.65μs -> 1.43μs (84.7% faster)


def test_multiple_styles_basic_nesting():
    # Multiple styles, nested, no flags
    styles = [("bfseries", ""), ("textcolor", "{red}")]
    # Should nest: \bfseries{\textcolor{red} baz}
    expected = r"\bfseries \textcolor{red} baz"
    codeflash_output = _parse_latex_cell_styles(
        styles, "baz"
    )  # 3.90μs -> 2.07μs (88.6% faster)


def test_multiple_styles_reversed_nesting():
    # Most recent style is innermost
    styles = [("bfseries", ""), ("textcolor", "{red}")]
    codeflash_output = _parse_latex_cell_styles(styles, "baz")
    result = codeflash_output  # 3.65μs -> 1.99μs (83.6% faster)


def test_wrap_flag_applied():
    # --wrap flag should wrap with curly braces
    styles = [("bfseries", "--wrap")]
    codeflash_output = _parse_latex_cell_styles(styles, "foo")
    result = codeflash_output  # 3.93μs -> 2.61μs (50.7% faster)


def test_nowrap_flag_applied():
    # --nowrap flag should not wrap
    styles = [("bfseries", "--nowrap")]
    codeflash_output = _parse_latex_cell_styles(styles, "foo")
    result = codeflash_output  # 3.72μs -> 2.60μs (43.4% faster)


def test_lwrap_flag_applied():
    # --lwrap flag should wrap command only
    styles = [("bfseries", "--lwrap")]
    codeflash_output = _parse_latex_cell_styles(styles, "foo")
    result = codeflash_output  # 3.87μs -> 2.61μs (48.2% faster)


def test_rwrap_flag_applied():
    # --rwrap flag should wrap display_value only
    styles = [("bfseries", "--rwrap")]
    codeflash_output = _parse_latex_cell_styles(styles, "foo")
    result = codeflash_output  # 3.67μs -> 2.61μs (40.8% faster)


def test_dwrap_flag_applied():
    # --dwrap flag should wrap both command and display_value
    styles = [("bfseries", "--dwrap")]
    codeflash_output = _parse_latex_cell_styles(styles, "foo")
    result = codeflash_output  # 3.92μs -> 2.80μs (40.0% faster)


def test_multiple_flags_applied_in_order():
    # Multiple styles, one with --wrap
    styles = [("bfseries", "--wrap"), ("textcolor", "{red}")]
    codeflash_output = _parse_latex_cell_styles(styles, "foo")
    result = codeflash_output  # 5.01μs -> 3.06μs (63.6% faster)


def test_strip_comments_and_whitespace_from_options():
    # Option with comments and whitespace
    styles = [("textcolor", "red /* --wrap */  ")]
    codeflash_output = _parse_latex_cell_styles(styles, "foo")
    result = codeflash_output  # 4.59μs -> 3.27μs (40.5% faster)


def test_convert_css_font_weight():
    # CSS conversion for font-weight
    styles = [("font-weight", "bold")]
    codeflash_output = _parse_latex_cell_styles(styles, "foo", convert_css=True)
    result = codeflash_output  # 6.03μs -> 7.03μs (14.2% slower)


def test_convert_css_font_style_italic():
    styles = [("font-style", "italic")]
    codeflash_output = _parse_latex_cell_styles(styles, "foo", convert_css=True)
    result = codeflash_output  # 5.84μs -> 6.50μs (10.1% slower)


def test_convert_css_color_named():
    styles = [("color", "red")]
    codeflash_output = _parse_latex_cell_styles(styles, "foo", convert_css=True)
    result = codeflash_output  # 6.46μs -> 7.60μs (14.9% slower)


def test_convert_css_color_hex():
    styles = [("color", "#ff23ee")]
    codeflash_output = _parse_latex_cell_styles(styles, "foo", convert_css=True)
    result = codeflash_output  # 7.15μs -> 8.02μs (10.9% slower)


def test_convert_css_color_short_hex():
    styles = [("color", "#f0e")]
    codeflash_output = _parse_latex_cell_styles(styles, "foo", convert_css=True)
    result = codeflash_output  # 7.60μs -> 8.73μs (12.9% slower)


def test_convert_css_color_rgb():
    styles = [("color", "rgb(128, 255, 0)")]
    codeflash_output = _parse_latex_cell_styles(styles, "foo", convert_css=True)
    result = codeflash_output  # 17.1μs -> 15.9μs (7.61% faster)


def test_convert_css_color_rgba():
    styles = [("color", "rgba(128, 255, 0, 0.5)")]
    codeflash_output = _parse_latex_cell_styles(styles, "foo", convert_css=True)
    result = codeflash_output  # 15.4μs -> 13.9μs (11.2% faster)


def test_convert_css_background_color_named():
    styles = [("background-color", "red")]
    codeflash_output = _parse_latex_cell_styles(styles, "foo", convert_css=True)
    result = codeflash_output  # 9.01μs -> 9.81μs (8.12% slower)


def test_convert_css_background_color_hex():
    styles = [("background-color", "#ff23ee")]
    codeflash_output = _parse_latex_cell_styles(styles, "foo", convert_css=True)
    result = codeflash_output  # 9.14μs -> 9.72μs (5.99% slower)


def test_convert_css_background_color_rgb():
    styles = [("background-color", "rgb(128, 255, 0)")]
    codeflash_output = _parse_latex_cell_styles(styles, "foo", convert_css=True)
    result = codeflash_output  # 18.3μs -> 16.8μs (8.95% faster)


def test_convert_css_with_flag():
    styles = [("font-weight", "bold--wrap")]
    codeflash_output = _parse_latex_cell_styles(styles, "foo", convert_css=True)
    result = codeflash_output  # 7.69μs -> 8.23μs (6.61% slower)


def test_convert_css_with_latex_tag():
    styles = [("bfseries", "--latex")]
    codeflash_output = _parse_latex_cell_styles(styles, "foo", convert_css=True)
    result = codeflash_output  # 5.02μs -> 5.82μs (13.7% slower)


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


def test_unknown_command_is_passed_through():
    # Unknown command, should still format as latex command
    styles = [("unknowncmd", "option")]
    codeflash_output = _parse_latex_cell_styles(styles, "foo")
    result = codeflash_output  # 2.65μs -> 1.47μs (79.8% faster)


def test_empty_display_value():
    # Empty display_value, should still format correctly
    styles = [("bfseries", "")]
    codeflash_output = _parse_latex_cell_styles(styles, "")
    result = codeflash_output  # 2.57μs -> 1.47μs (75.2% faster)


def test_empty_option():
    # Empty option string
    styles = [("bfseries", "")]
    codeflash_output = _parse_latex_cell_styles(styles, "foo")
    result = codeflash_output  # 2.63μs -> 1.48μs (78.5% faster)


def test_option_is_float():
    # Option as float
    styles = [("bfseries", 123.45)]
    codeflash_output = _parse_latex_cell_styles(styles, "foo")
    result = codeflash_output  # 5.81μs -> 4.11μs (41.4% faster)


def test_flag_in_middle_of_option():
    # Flag appears in middle of option string
    styles = [("bfseries", "abc--wrapdef")]
    codeflash_output = _parse_latex_cell_styles(styles, "foo")
    result = codeflash_output  # 4.19μs -> 2.97μs (41.3% faster)


def test_multiple_flags_only_first_applied():
    # Multiple flags in option, only first applied
    styles = [("bfseries", "abc--wrap--rwrap")]
    codeflash_output = _parse_latex_cell_styles(styles, "foo")
    result = codeflash_output  # 3.92μs -> 2.86μs (36.9% faster)


def test_non_string_option():
    # Option is not string (float)
    styles = [("bfseries", 42.0)]
    codeflash_output = _parse_latex_cell_styles(styles, "bar")
    result = codeflash_output  # 4.32μs -> 2.88μs (49.9% faster)


def test_convert_css_font_weight_not_bold():
    # font-weight not bold/bolder, should not convert
    styles = [("font-weight", "normal")]
    codeflash_output = _parse_latex_cell_styles(styles, "foo", convert_css=True)
    result = codeflash_output  # 4.30μs -> 6.18μs (30.5% slower)


def test_convert_css_font_style_not_italic():
    # font-style not italic/oblique, should not convert
    styles = [("font-style", "normal")]
    codeflash_output = _parse_latex_cell_styles(styles, "foo", convert_css=True)
    result = codeflash_output  # 3.99μs -> 5.94μs (32.8% slower)


def test_convert_css_unknown_attribute():
    # Unknown CSS attribute, should not convert
    styles = [("unknown", "value")]
    codeflash_output = _parse_latex_cell_styles(styles, "foo", convert_css=True)
    result = codeflash_output  # 3.02μs -> 4.87μs (37.9% slower)


def test_convert_css_with_flag_and_comment():
    # CSS option with flag and comment
    styles = [("font-weight", "bold /* --wrap */ ")]
    codeflash_output = _parse_latex_cell_styles(styles, "foo", convert_css=True)
    result = codeflash_output  # 8.77μs -> 9.19μs (4.52% slower)


def test_convert_css_multiple_styles():
    # Multiple CSS styles
    styles = [
        ("font-weight", "bold"),
        ("color", "#f0e"),
        ("font-style", "italic"),
    ]
    codeflash_output = _parse_latex_cell_styles(styles, "foo", convert_css=True)
    result = codeflash_output  # 12.4μs -> 11.8μs (5.24% faster)


def test_convert_css_background_color_with_wrap_flag():
    styles = [("background-color", "red--wrap")]
    codeflash_output = _parse_latex_cell_styles(styles, "foo", convert_css=True)
    result = codeflash_output  # 9.02μs -> 9.31μs (3.19% slower)


def test_convert_css_color_with_wrap_flag():
    styles = [("color", "red--wrap")]
    codeflash_output = _parse_latex_cell_styles(styles, "foo", convert_css=True)
    result = codeflash_output  # 8.58μs -> 9.14μs (6.18% slower)


def test_convert_css_color_with_lwrap_flag():
    styles = [("color", "red--lwrap")]
    codeflash_output = _parse_latex_cell_styles(styles, "foo", convert_css=True)
    result = codeflash_output  # 8.56μs -> 9.68μs (11.6% slower)


def test_convert_css_color_with_rwrap_flag():
    styles = [("color", "red--rwrap")]
    codeflash_output = _parse_latex_cell_styles(styles, "foo", convert_css=True)
    result = codeflash_output  # 8.85μs -> 9.84μs (10.0% slower)


def test_convert_css_color_with_dwrap_flag():
    styles = [("color", "red--dwrap")]
    codeflash_output = _parse_latex_cell_styles(styles, "foo", convert_css=True)
    result = codeflash_output  # 8.82μs -> 9.62μs (8.28% slower)


def test_convert_css_background_color_with_lwrap_flag():
    styles = [("background-color", "red--lwrap")]
    codeflash_output = _parse_latex_cell_styles(styles, "foo", convert_css=True)
    result = codeflash_output  # 8.57μs -> 9.57μs (10.4% slower)


def test_convert_css_background_color_with_rwrap_flag():
    styles = [("background-color", "red--rwrap")]
    codeflash_output = _parse_latex_cell_styles(styles, "foo", convert_css=True)
    result = codeflash_output  # 8.73μs -> 9.10μs (4.02% slower)


def test_convert_css_background_color_with_dwrap_flag():
    styles = [("background-color", "red--dwrap")]
    codeflash_output = _parse_latex_cell_styles(styles, "foo", convert_css=True)
    result = codeflash_output  # 8.51μs -> 9.60μs (11.4% slower)


def test_convert_css_color_rgb_percent():
    styles = [("color", "rgb(50%, 100%, 0%)")]
    codeflash_output = _parse_latex_cell_styles(styles, "foo", convert_css=True)
    result = codeflash_output  # 17.9μs -> 16.7μs (7.56% faster)


def test_convert_css_color_rgb_with_spaces():
    styles = [("color", "rgb( 128 , 255 , 0 )")]
    codeflash_output = _parse_latex_cell_styles(styles, "foo", convert_css=True)
    result = codeflash_output  # 15.9μs -> 14.7μs (8.12% faster)


def test_convert_css_color_rgba_with_percent():
    styles = [("color", "rgba(50%, 100%, 0%, 0.5)")]
    codeflash_output = _parse_latex_cell_styles(styles, "foo", convert_css=True)
    result = codeflash_output  # 16.3μs -> 14.7μs (10.6% faster)


def test_convert_css_background_color_rgb_percent():
    styles = [("background-color", "rgb(50%, 100%, 0%)")]
    codeflash_output = _parse_latex_cell_styles(styles, "foo", convert_css=True)
    result = codeflash_output  # 17.8μs -> 16.3μs (9.33% faster)


def test_convert_css_background_color_rgba_percent():
    styles = [("background-color", "rgba(50%, 100%, 0%, 0.5)")]
    codeflash_output = _parse_latex_cell_styles(styles, "foo", convert_css=True)
    result = codeflash_output  # 17.8μs -> 15.9μs (12.1% faster)


def test_convert_css_with_multiple_flags():
    styles = [("font-weight", "bold--wrap--rwrap")]
    codeflash_output = _parse_latex_cell_styles(styles, "foo", convert_css=True)
    result = codeflash_output  # 4.85μs -> 6.64μs (26.9% slower)


def test_convert_css_with_flag_and_comment_and_spaces():
    styles = [("font-weight", "bold /* --wrap */   ")]
    codeflash_output = _parse_latex_cell_styles(styles, "foo", convert_css=True)
    result = codeflash_output  # 8.14μs -> 8.55μs (4.81% slower)


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


def test_large_number_of_styles_basic():
    # 1000 basic styles, no flags
    styles = [("cmd" + str(i), "") for i in range(1000)]
    codeflash_output = _parse_latex_cell_styles(styles, "foo")
    result = codeflash_output  # 1.11ms -> 225μs (390% faster)
    # Should nest all, innermost is last cmd
    expected = "foo"
    for i in reversed(range(1000)):
        expected = f"\\cmd{i} {expected}"


def test_large_number_of_styles_with_wrap_flag():
    # 1000 styles, all with --wrap
    styles = [("cmd" + str(i), "--wrap") for i in range(1000)]
    codeflash_output = _parse_latex_cell_styles(styles, "foo")
    result = codeflash_output  # 2.03ms -> 504μs (302% faster)
    # Each should wrap around previous
    expected = "foo"
    for i in reversed(range(1000)):
        expected = f"{{\\cmd{i} {expected}}}"


def test_large_number_of_styles_mixed_flags():
    # 500 with --wrap, 500 with --rwrap
    styles = [("cmd" + str(i), "--wrap") for i in range(500)] + [
        ("cmd" + str(i + 500), "--rwrap") for i in range(500)
    ]
    codeflash_output = _parse_latex_cell_styles(styles, "foo")
    result = codeflash_output  # 2.05ms -> 572μs (258% faster)
    expected = "foo"
    for i in reversed(range(500, 1000)):
        expected = f"\\cmd{i}{{{expected}}}"
    for i in reversed(range(500)):
        expected = f"{{\\cmd{i} {expected}}}"


def test_large_number_of_css_styles_conversion():
    # 500 font-weight, 500 color
    styles = [("font-weight", "bold")] * 500 + [("color", "red")] * 500
    codeflash_output = _parse_latex_cell_styles(styles, "foo", convert_css=True)
    result = codeflash_output  # 1.71ms -> 615μs (178% faster)
    expected = "foo"
    for _ in range(500):
        expected = r"\color{red} " + expected
    for _ in range(500):
        expected = r"\bfseries " + expected


def test_large_number_of_css_styles_with_flags():
    # 500 font-weight with --wrap, 500 color with --rwrap
    styles = [("font-weight", "bold--wrap")] * 500 + [("color", "red--rwrap")] * 500
    codeflash_output = _parse_latex_cell_styles(styles, "foo", convert_css=True)
    result = codeflash_output  # 3.50ms -> 1.24ms (181% faster)
    expected = "foo"
    for _ in range(500):
        expected = r"\color{red}{%s}" % expected
    for _ in range(500):
        expected = r"{\bfseries %s}" % expected


def test_large_scale_performance():
    # Large scale, mixed styles, check result length
    styles = []
    for i in range(250):
        styles.append(("font-weight", "bold"))
        styles.append(("color", "#ff23ee"))
        styles.append(("bfseries", "--wrap"))
        styles.append(("textcolor", "{red}"))
    codeflash_output = _parse_latex_cell_styles(styles, "foo", convert_css=True)
    result = codeflash_output  # 855μs -> 370μs (131% faster)


def test_large_scale_edge_case_empty_options():
    # 1000 styles with empty option
    styles = [("cmd" + str(i), "") for i in range(1000)]
    codeflash_output = _parse_latex_cell_styles(styles, "foo")
    result = codeflash_output  # 1.12ms -> 237μs (372% faster)
    # Should nest all, innermost is last cmd
    expected = "foo"
    for i in reversed(range(1000)):
        expected = f"\\cmd{i} {expected}"


def test_large_scale_edge_case_float_options():
    # 1000 styles with float options
    styles = [("cmd" + str(i), float(i)) for i in range(1000)]
    codeflash_output = _parse_latex_cell_styles(styles, "foo")
    result = codeflash_output  # 1.89ms -> 483μs (291% faster)
    expected = "foo"
    for i in reversed(range(1000)):
        expected = f"\\cmd{i}{float(i)} {expected}"


# 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-_parse_latex_cell_styles-mio8bna7 and push.

Codeflash Static Badge

The optimization achieves a **199% speedup** by eliminating redundant operations and reducing object allocations in the core processing loop of `_parse_latex_cell_styles`.

**Key optimizations:**

1. **Eliminated formatter dictionary creation**: The original code created a 5-element dictionary on every iteration (9,095 times), causing significant overhead. The optimized version uses direct conditional branches instead, reducing allocation and lookup costs.

2. **Reduced string conversions**: `str(options)` was called multiple times per iteration. Now it's computed once and stored as `options_str`, eliminating redundant conversions.

3. **Precompiled regex patterns**: Moved regex compilation outside the `color` function to avoid recompiling patterns on each CSS color conversion, improving RGB/RGBA parsing performance.

4. **Optimized wrap argument handling**: Extracted `_WRAP_ARGS` as a module-level constant and converted to tuple for membership tests, reducing list recreation overhead.

5. **Simplified list operations**: Replaced `.extend([single_item])` with `.append(single_item)` to avoid unnecessary list wrapping.

**Performance impact by test type:**
- **Basic LaTeX styling** (no CSS conversion): 40-90% faster due to eliminated formatter dictionary creation
- **Large-scale operations** (1000+ styles): 200-400% faster, showing excellent scalability  
- **CSS conversion cases**: Mixed results - simple conversions are slightly slower due to tuple conversion overhead, but complex RGB/RGBA parsing is 8-12% faster due to precompiled regex

The function is called from `_parse_latex_header_span` for table cell formatting in pandas styling, making this optimization beneficial for LaTeX export performance, especially with complex styled DataFrames containing many cells.
@codeflash-ai codeflash-ai bot requested a review from mashraf-222 December 2, 2025 07:01
@codeflash-ai codeflash-ai bot added ⚡️ codeflash Optimization PR opened by Codeflash AI 🎯 Quality: High Optimization Quality according to Codeflash labels Dec 2, 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