bugraoz93 commented on code in PR #57718:
URL: https://github.com/apache/airflow/pull/57718#discussion_r2487719021


##########
airflow-ctl/src/airflowctl/api/client.py:
##########
@@ -214,6 +231,79 @@ def __init__(
             **kwargs,
         )
 
+    def _clean_empty_values(self, data: dict[str, Any]) -> dict[str, Any]:
+        """
+        Recursively remove keys with None or empty values from a dictionary if 
they are not required in the datamodels.
+
+        Args:
+            data (dict): The input dictionary to clean.
+        Returns:
+            dict: The cleaned dictionary with empty values removed.
+        """
+        if not self.datamodel:
+            return data
+        # Check each datamodel and clean if field is nullable
+        cleaned_data = {}
+        for datamodel in self.datamodel:
+            # Create map from field name and required status
+            required_fields = []
+            for field_name, field_info in 
datamodel.__pydantic_fields__.items():
+                if field_info.is_required():
+                    required_fields.append(field_name)
+
+            for key, value in data.items():
+                if key in required_fields:
+                    cleaned_data[key] = value
+                else:
+                    # clean only if value is not None or empty
+                    if value is not None:
+                        if isinstance(value, dict):
+                            cleaned_data[key] = self._clean_empty_values(value)
+                        else:
+                            cleaned_data[key] = value
+        return cleaned_data
+
+    # Override request method to include more validation
+    def request(
+        self,
+        method: str,
+        url: URL | str,
+        *,
+        content: RequestContent | None = None,
+        data: RequestData | None = None,
+        files: RequestFiles | None = None,
+        json: typing.Any | None = None,
+        params: QueryParamTypes | None = None,
+        headers: HeaderTypes | None = None,
+        cookies: CookieTypes | None = None,
+        auth: AuthTypes | UseClientDefault | None = USE_CLIENT_DEFAULT,
+        follow_redirects: bool | UseClientDefault = USE_CLIENT_DEFAULT,
+        timeout: TimeoutTypes | UseClientDefault = USE_CLIENT_DEFAULT,
+        extensions: RequestExtensions | None = None,
+    ) -> Response:
+        """Make a request with the client."""
+        # Include any validation below if needed
+        if json is not None:
+            # Validate JSON body before sending the request and cleanse empty 
values
+            # This is needed because of model_dump including None values for 
optional fields which send to API as empty
+            json = self._clean_empty_values(data=json)

Review Comment:
   My idea was more of a middleware interceptor to prepare for further cases. 
If it doesn't make sense here, I will include this layer for Pydantic in the 
future when needed. This seems solved more easily with Pydantic, indeed. 
Thanks, Ash! Better error message for the validation next



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to