SEPURI-SAI-KRISHNA commented on code in PR #45083:
URL: https://github.com/apache/superset/pull/45083#discussion_r4275020002


##########
superset/utils/pandas_postprocessing/utils.py:
##########
@@ -248,14 +258,24 @@ def _append_columns(
         # caller which mutates the result does not reach `base_df`.
         return base_df.copy()
 
-    overwritten = {key: value for key, value in columns.items() if key == 
value}
-    appended = {key: value for key, value in columns.items() if key != value}
+    appended = {
+        key: value
+        for key, value in columns.items()
+        if value != key and value not in base_df.columns
+    }
+    overwritten = {key: value for key, value in columns.items() if key not in 
appended}
 
     _base_df = base_df
     if overwritten:
         # make sure to return a new DataFrame instead of changing the 
`base_df`.
         _base_df = base_df.copy()
-        _base_df.loc[:, overwritten.keys()] = append_df
+        # Select before renaming, as below, and because once the source name 
may
+        # differ from the target, it is the target that says which column to
+        # write.
+        overwritten_df = append_df.loc[:, overwritten.keys()].rename(
+            columns=overwritten
+        )
+        _base_df.loc[:, overwritten_df.columns] = overwritten_df

Review Comment:
   Good catch, and it is worse than non-blocking: this PR introduces the 500. 
Confirmed by running both versions of `_append_columns` against the same frames:
   
   ```
   master
     OK     {"y":"z","z":"z"} -> cols=['y', 'z', 'z']
     OK     {"y":"w","z":"w"} -> cols=['y', 'z', 'w', 'w']
   this PR
     RAISES {"y":"z","z":"z"} -> ValueError: Setting with non-unique columns is 
not allowed.
     OK     {"y":"w","z":"w"} -> cols=['y', 'z', 'w', 'w']
   ```
   
   So I took your suggestion rather than leaving it as a follow-up, and 
rejected duplicate targets up front. It covers both rows, since no split of the 
mapping can serve two sources writing to one target.
   
   ```
   this PR + guard
     RAISES {"y":"z","z":"z"} -> InvalidPostProcessingError: Columns mapped to 
the same target: z
     RAISES {"y":"w","z":"w"} -> InvalidPostProcessingError: Columns mapped to 
the same target: w
     OK     {"y":"z","z":"y"} -> cols=['y', 'z']
     OK     {"y":"z"}         -> cols=['y', 'z']
   ```
   
   `InvalidPostProcessingError.status` is 400, and measured through the real 
operations it is a 400 in each: `rolling`, `cum` and `diff` all return `Columns 
mapped to the same target: z`.
   
   One thing the guard fixes that is not obvious from the line you commented 
on. `geohash_decode` and `geodetic_parse` already wrap `_append_columns` in 
`except ValueError: raise InvalidPostProcessingError(_("Invalid geodetic 
string"))`, so for those two callers the `ValueError` was arriving as a 400 
with the wrong cause named. Raising inside `_append_columns` goes past that:
   
   ```
   geodetic_parse(df, geodetic="p", longitude="x", latitude="x")
     -> InvalidPostProcessingError: Columns mapped to the same target: x  
status=400
   ```
   
   Added as a parametrized test over both of your mappings. 193 passed in 
`tests/unit_tests/pandas_postprocessing/`, and the new string is in 
`messages.pot`.



-- 
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]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to