11# cython: language=c++
2+ # cython: boundscheck=False
3+ # cython: wraparound=False
4+ # cython: cdivision=True
25
36from typing import Any
47
@@ -10,6 +13,7 @@ from flask_inputfilter.models.cimports cimport BaseFilter, BaseValidator, FieldM
1013
1114# Compile-time constants for performance thresholds
1215DEF LARGE_DATASET_THRESHOLD = 10
16+ DEF SMALL_DICT_THRESHOLD = 5
1317
1418
1519cdef class DataMixin:
@@ -35,19 +39,22 @@ cdef class DataMixin:
3539 if not data and fields:
3640 return True
3741
38- cdef set field_set
42+ cdef:
43+ set field_set
44+ Py_ssize_t field_count = len (fields)
45+ Py_ssize_t data_count = len (data)
3946
40- # Use set operations for faster lookup when there are many fields
41- if len (fields) > LARGE_DATASET_THRESHOLD:
47+ if field_count > LARGE_DATASET_THRESHOLD and data_count > SMALL_DICT_THRESHOLD:
4248 field_set = set (fields.keys())
4349 for field_name in data.keys():
4450 if field_name not in field_set:
4551 return True
46- else :
47- # Use direct dict lookup for smaller field counts
52+ elif data_count < field_count:
4853 for field_name in data.keys():
4954 if field_name not in fields:
5055 return True
56+ else :
57+ return bool (set (data.keys()) - set (fields.keys()))
5158
5259 return False
5360
@@ -72,19 +79,27 @@ cdef class DataMixin:
7279 """
7380 cdef:
7481 dict [str , Any] filtered_data = {}
75- Py_ssize_t i, n = len (data) if data else 0
76- list keys = list (data.keys()) if n > 0 else []
77- list values = list (data.values()) if n > 0 else []
82+ Py_ssize_t i, n = len (data) if data is not None else 0
83+ list keys
84+ list values
7885 str field_name
7986 object field_value
87+ FieldModel field_info
88+
89+ if n == 0 :
90+ return filtered_data
91+
92+ keys = list (data.keys())
93+ values = list (data.values())
8094
8195 for i in range (n):
8296 field_name = keys[i]
8397 field_value = values[i]
84-
85- if field_name in fields:
98+
99+ field_info = fields.get(field_name)
100+ if field_info is not None :
86101 field_value = ValidationMixin.apply_filters(
87- fields[field_name] .filters,
102+ field_info .filters,
88103 global_filters,
89104 field_value,
90105 )
@@ -125,8 +140,8 @@ cdef class DataMixin:
125140 fields, data, global_filters, global_validators
126141 )
127142
128- # Check conditions if present and no errors yet
129- if conditions and not errors:
143+ # Check conditions only if present and no errors yet
144+ if conditions is not None and len (conditions) > 0 and not errors:
130145 try :
131146 ValidationMixin.check_conditions(conditions, validated_data)
132147 except ValidationError as e:
@@ -150,13 +165,18 @@ cdef class DataMixin:
150165 cdef:
151166 Py_ssize_t i, n
152167 dict source_inputs = source_filter.get_inputs()
153- list keys = list (source_inputs.keys()) if source_inputs else []
154- list new_fields = list (source_inputs.values()) if source_inputs else []
168+ list keys
169+ list new_fields
170+
171+ if source_inputs:
172+ keys = list (source_inputs.keys())
173+ new_fields = list (source_inputs.values())
174+ n = len (keys)
155175
156- # Merge fields efficiently
157- n = len ( keys)
158- for i in range (n) :
159- target_filter.fields[keys[i]] = new_fields[i]
176+ for i in range (n):
177+ target_filter.fields[ keys[i]] = new_fields[i]
178+ else :
179+ n = 0
160180
161181 # Merge conditions
162182 target_filter.conditions.extend(source_filter.conditions)
@@ -183,13 +203,19 @@ cdef class DataMixin:
183203 - **target_list** (*list*): The list to merge into.
184204 - **source_list** (*list*): The list to merge from.
185205 """
186- cdef dict existing_type_map
187-
206+ cdef:
207+ dict existing_type_map = {}
208+ Py_ssize_t i, n = len (target_list)
209+ object component
210+ type component_type
211+
212+ for i in range (n):
213+ existing_type_map[type (target_list[i])] = i
214+
188215 for component in source_list:
189- existing_type_map = {
190- type (v): i for i, v in enumerate (target_list)
191- }
192- if type (component) in existing_type_map:
193- target_list[existing_type_map[type (component)]] = component
216+ component_type = type (component)
217+ if component_type in existing_type_map:
218+ target_list[existing_type_map[component_type]] = component
194219 else :
195- target_list.append(component)
220+ target_list.append(component)
221+ existing_type_map[component_type] = len (target_list) - 1
0 commit comments