Skip to content

Conversation

@codeflash-ai
Copy link

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

📄 15% (0.15x) speedup for ModelAdminChecks._check_search_fields in django/contrib/admin/checks.py

⏱️ Runtime : 59.6 microseconds 51.9 microseconds (best of 90 runs)

📝 Explanation and details

Optimization Rationale:

  • Inlining the must_be logic inside _check_search_fields eliminates a function call and local stack setup, resulting in faster execution for this hot code path.
  • Using an f-string for error message construction instead of "The value of '%s' must be %s." % (option, type) improves string formatting performance in Python 3.11 and later.
  • Keeps the standalone must_be function for behavioral preservation and compatibility elsewhere, but hot path avoids the call.
  • All comments, behavior, exceptions, and original code style are strictly preserved.

Correctness verification report:

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

# imports
import pytest
from django.contrib.admin.checks import ModelAdminChecks

# ------------------- UNIT TESTS -------------------

# Helper for creating dummy admin objects
def make_admin(search_fields):
    # Use SimpleNamespace for easy attribute assignment
    return SimpleNamespace(search_fields=search_fields)

# 1. Basic Test Cases
def test_search_fields_list():
    """Should pass with a list of strings."""
    obj = make_admin(['name', 'email'])
    mac = ModelAdminChecks()
    codeflash_output = mac._check_search_fields(obj); result = codeflash_output # 581ns -> 548ns (6.02% faster)

def test_search_fields_tuple():
    """Should pass with a tuple of strings."""
    obj = make_admin(('name', 'email'))
    mac = ModelAdminChecks()
    codeflash_output = mac._check_search_fields(obj); result = codeflash_output # 619ns -> 640ns (3.28% slower)

def test_search_fields_empty_list():
    """Should pass with an empty list."""
    obj = make_admin([])
    mac = ModelAdminChecks()
    codeflash_output = mac._check_search_fields(obj); result = codeflash_output # 552ns -> 542ns (1.85% faster)

def test_search_fields_empty_tuple():
    """Should pass with an empty tuple."""
    obj = make_admin(())
    mac = ModelAdminChecks()
    codeflash_output = mac._check_search_fields(obj); result = codeflash_output # 595ns -> 597ns (0.335% slower)

# 2. Edge Test Cases









def test_search_fields_nested_list():
    """Should pass if search_fields is a list of lists (still a list)."""
    obj = make_admin([['name'], ['email']])
    mac = ModelAdminChecks()
    codeflash_output = mac._check_search_fields(obj); result = codeflash_output # 813ns -> 822ns (1.09% slower)

def test_search_fields_tuple_of_lists():
    """Should pass if search_fields is a tuple of lists."""
    obj = make_admin((['name'], ['email']))
    mac = ModelAdminChecks()
    codeflash_output = mac._check_search_fields(obj); result = codeflash_output # 688ns -> 674ns (2.08% faster)

def test_search_fields_list_of_ints():
    """Should pass if search_fields is a list of ints (type check only cares about container)."""
    obj = make_admin([1, 2, 3])
    mac = ModelAdminChecks()
    codeflash_output = mac._check_search_fields(obj); result = codeflash_output # 598ns -> 571ns (4.73% faster)

# 3. Large Scale Test Cases

def test_search_fields_large_list():
    """Should pass with a large list of fields."""
    fields = [f'field_{i}' for i in range(1000)]
    obj = make_admin(fields)
    mac = ModelAdminChecks()
    codeflash_output = mac._check_search_fields(obj); result = codeflash_output # 564ns -> 540ns (4.44% faster)

def test_search_fields_large_tuple():
    """Should pass with a large tuple of fields."""
    fields = tuple(f'field_{i}' for i in range(1000))
    obj = make_admin(fields)
    mac = ModelAdminChecks()
    codeflash_output = mac._check_search_fields(obj); result = codeflash_output # 675ns -> 659ns (2.43% faster)


def test_search_fields_large_string():
    """Should fail with a large string."""
    obj = make_admin('a' * 1000)
    mac = ModelAdminChecks()
    codeflash_output = mac._check_search_fields(obj); result = codeflash_output
    expected = must_be("a list or tuple", "search_fields", obj, "admin.E126")

# 4. Parametrized tests for multiple invalid types
@pytest.mark.parametrize("invalid_value", [
    123, 12.5, None, True, False, {'a': 1}, set(['x']), b'abc', (x for x in range(2))
])
def test_search_fields_various_invalid_types(invalid_value):
    """Should fail for various invalid types."""
    obj = make_admin(invalid_value)
    mac = ModelAdminChecks()
    codeflash_output = mac._check_search_fields(obj); result = codeflash_output
    expected = must_be("a list or tuple", "search_fields", obj, "admin.E126")

# 5. Parametrized tests for valid containers
@pytest.mark.parametrize("valid_value", [
    [], (), ['a'], ('a',), [1, 2], (1, 2), [None], (None,), [[1], [2]], (['a'], ['b'])
])
def test_search_fields_various_valid_types(valid_value):
    """Should pass for various valid sequence types."""
    obj = make_admin(valid_value)
    mac = ModelAdminChecks()
    codeflash_output = mac._check_search_fields(obj); result = codeflash_output # 6.13μs -> 6.19μs (0.953% slower)
# codeflash_output is used to check that the output of the original code is the same as that of the optimized code.
#------------------------------------------------
import pytest
from django.contrib.admin.checks import ModelAdminChecks
# function to test
from django.core import checks


# Helper class to mimic admin objects
class DummyAdmin:
    def __init__(self, search_fields):
        self.search_fields = search_fields

# Basic Test Cases

def test_search_fields_list():
    # Should pass with a list
    obj = DummyAdmin(['field1', 'field2'])
    codeflash_output = ModelAdminChecks()._check_search_fields(obj); result = codeflash_output # 519ns -> 495ns (4.85% faster)

def test_search_fields_tuple():
    # Should pass with a tuple
    obj = DummyAdmin(('field1', 'field2'))
    codeflash_output = ModelAdminChecks()._check_search_fields(obj); result = codeflash_output # 602ns -> 567ns (6.17% faster)

def test_search_fields_empty_list():
    # Should pass with an empty list
    obj = DummyAdmin([])
    codeflash_output = ModelAdminChecks()._check_search_fields(obj); result = codeflash_output # 509ns -> 538ns (5.39% slower)

def test_search_fields_empty_tuple():
    # Should pass with an empty tuple
    obj = DummyAdmin(())
    codeflash_output = ModelAdminChecks()._check_search_fields(obj); result = codeflash_output # 540ns -> 578ns (6.57% slower)

# Edge Test Cases



def test_search_fields_float():
    # Should fail with a float
    obj = DummyAdmin(3.14)
    codeflash_output = ModelAdminChecks()._check_search_fields(obj); result = codeflash_output # 2.56μs -> 2.27μs (12.6% faster)




def test_search_fields_large_list():
    # Should pass with a large list
    large_list = ['field' + str(i) for i in range(1000)]
    obj = DummyAdmin(large_list)
    codeflash_output = ModelAdminChecks()._check_search_fields(obj); result = codeflash_output # 550ns -> 533ns (3.19% faster)

def test_search_fields_large_tuple():
    # Should pass with a large tuple
    large_tuple = tuple('field' + str(i) for i in range(1000))
    obj = DummyAdmin(large_tuple)
    codeflash_output = ModelAdminChecks()._check_search_fields(obj); result = codeflash_output # 554ns -> 622ns (10.9% slower)


def test_search_fields_large_dict():
    # Should fail with a large dict
    large_dict = {'field' + str(i): i for i in range(1000)}
    obj = DummyAdmin(large_dict)
    codeflash_output = ModelAdminChecks()._check_search_fields(obj); result = codeflash_output # 3.06μs -> 2.39μs (27.7% faster)

# Unusual/Edge: Nested structures

def test_search_fields_nested_list():
    # Should pass with a nested list (list inside list)
    obj = DummyAdmin([['field1', 'field2'], 'field3'])
    codeflash_output = ModelAdminChecks()._check_search_fields(obj); result = codeflash_output # 537ns -> 544ns (1.29% slower)

def test_search_fields_nested_tuple():
    # Should pass with a nested tuple (tuple inside tuple)
    obj = DummyAdmin((('field1', 'field2'), 'field3'))
    codeflash_output = ModelAdminChecks()._check_search_fields(obj); result = codeflash_output # 544ns -> 623ns (12.7% slower)

# Edge: Mixed types in sequence

def test_search_fields_mixed_types_in_list():
    # Should pass as long as outer type is list
    obj = DummyAdmin(['field1', 2, None, True, ['nested']])
    codeflash_output = ModelAdminChecks()._check_search_fields(obj); result = codeflash_output # 504ns -> 507ns (0.592% slower)

def test_search_fields_mixed_types_in_tuple():
    # Should pass as long as outer type is tuple
    obj = DummyAdmin(('field1', 2, None, True, ('nested',)))
    codeflash_output = ModelAdminChecks()._check_search_fields(obj); result = codeflash_output # 570ns -> 602ns (5.32% slower)

# Edge: Immutable sequence

def test_search_fields_frozenset():
    # Should fail with frozenset (not list or tuple)
    obj = DummyAdmin(frozenset(['field1', 'field2']))
    codeflash_output = ModelAdminChecks()._check_search_fields(obj); result = codeflash_output # 3.65μs -> 2.73μs (33.8% faster)

# Edge: Generator


def test_search_fields_range():
    # Should fail with range object
    obj = DummyAdmin(range(2))
    codeflash_output = ModelAdminChecks()._check_search_fields(obj); result = codeflash_output # 2.88μs -> 2.25μs (28.0% 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-ModelAdminChecks._check_search_fields-mhcicrvz and push.

Codeflash

**Optimization Rationale:**

- Inlining the `must_be` logic inside `_check_search_fields` eliminates a function call and local stack setup, resulting in faster execution for this hot code path.
- Using an f-string for error message construction instead of `"The value of '%s' must be %s." % (option, type)` improves string formatting performance in Python 3.11 and later.
- Keeps the standalone `must_be` function for behavioral preservation and compatibility elsewhere, but hot path avoids the call.
- All comments, behavior, exceptions, and original code style are strictly preserved.
@codeflash-ai codeflash-ai bot requested a review from mashraf-222 October 29, 2025 21:29
@codeflash-ai codeflash-ai bot added the ⚡️ codeflash Optimization PR opened by Codeflash AI label Oct 29, 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