From 648ded9574f0f3d3688d49694cd25f5ae40476bd Mon Sep 17 00:00:00 2001 From: Quaylyn Rimer <31830590+killerdevildog@users.noreply.github.com> Date: Thu, 30 Oct 2025 10:07:24 -0600 Subject: [PATCH] Fix mutable default arguments in OrderingFilter methods (#9742) * Install and configure flake8-bugbear to spot mutable default arguments * Fix mutable default arguments in OrderingFilter methods - Fixed get_default_valid_fields() and get_valid_fields() methods in filters.py - Changed context={} default parameter to context=None to prevent mutable default anti-pattern - Added proper None checking with context = {} assignment inside methods Why this fix is important: - Mutable default arguments (context={}) create shared state across function calls - Same dict object gets reused, potentially causing unexpected side effects - This is a well-known Python anti-pattern that can lead to bugs What was changed: - Line 249: get_default_valid_fields(self, queryset, view, context=None) - Line 285: get_valid_fields(self, queryset, view, context=None) - Added 'if context is None: context = {}' in both methods Testing results: - All existing filter tests pass (pytest tests/test_filters.py) - Custom verification script confirms fix works correctly - Maintains backward compatibility - No breaking changes to API Addresses GitHub issue #9741 --------- Co-authored-by: Bruno Alla --- .pre-commit-config.yaml | 1 + rest_framework/filters.py | 8 ++++++-- setup.cfg | 3 ++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 244d670b8..5780c8e31 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -18,6 +18,7 @@ repos: - id: flake8 additional_dependencies: - flake8-tidy-imports + - flake8-bugbear - repo: https://github.com/adamchainz/blacken-docs rev: 1.20.0 hooks: diff --git a/rest_framework/filters.py b/rest_framework/filters.py index 3f4730da8..010c87374 100644 --- a/rest_framework/filters.py +++ b/rest_framework/filters.py @@ -249,7 +249,9 @@ class OrderingFilter(BaseFilterBackend): return (ordering,) return ordering - def get_default_valid_fields(self, queryset, view, context={}): + def get_default_valid_fields(self, queryset, view, context=None): + if context is None: + context = {} # If `ordering_fields` is not specified, then we determine a default # based on the serializer class, if one exists on the view. if hasattr(view, 'get_serializer_class'): @@ -286,7 +288,9 @@ class OrderingFilter(BaseFilterBackend): ) ] - def get_valid_fields(self, queryset, view, context={}): + def get_valid_fields(self, queryset, view, context=None): + if context is None: + context = {} valid_fields = getattr(view, 'ordering_fields', self.ordering_fields) if valid_fields is None: diff --git a/setup.cfg b/setup.cfg index aebdf5362..6553bfcd5 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,3 +1,4 @@ [flake8] -ignore = E501,W503,W504 +extend-ignore = E501,W503,W504,B +extend-select = B006 banned-modules = json = use from rest_framework.utils import json!