SEPURI-SAI-KRISHNA opened a new pull request, #45018:
URL: https://github.com/apache/superset/pull/45018

   ### SUMMARY
   
   `_append_columns` chose between overwriting and appending with `all()`, so a 
mapping that did both fell entirely to the append path and re-appended the 
column that should have been overwritten, leaving two columns under one label. 
Details and provenance in #45017.
   
   This PR splits the mapping and handles each half, and selects the mapped 
columns before renaming them:
   
   ```python
   overwritten = {key: value for key, value in columns.items() if key == value}
   appended = {key: value for key, value in columns.items() if key != value}
   ```
   
   | mapping | before | after |
   |---|---|---|
   | `{"y": "y", "z": "z"}` | `['y', 'z']` | `['y', 'z']` (unchanged) |
   | `{"y": "y2", "z": "z2"}` | `['y', 'z', 'y2', 'z2']` | `['y', 'z', 'y2', 
'z2']` (unchanged) |
   | `{"y": "y", "z": "z2"}` | `['y', 'z', 'y', 'z2']` | `['y', 'z', 'z2']` |
   
   ### Two defects, one cause
   
   **1. A mixed mapping duplicates a label.** `cum`, `rolling` and `diff` 
restrict `append_df` to the mapped columns, so for them this is the only 
symptom. On MultiIndex columns, cumulating one metric in place after a pivot 
while adding another alongside it, it duplicates `('sum_metric', 'UK')` and 
`('sum_metric', 'US')`, and `df[label]` then hands callers a DataFrame where 
they expect a Series.
   
   **2. The append path carried columns the mapping never asked for.** The 
three geography operators build a working frame wider than their mapping, so 
they hit this independently of a mixed mapping:
   
   ```python
   # geodetic_parse always parses an altitude, but maps it only when asked
   geodetic_parse(df=..., geodetic="geodetic", latitude="lat", longitude="lon")
   # before: ['city', 'geodetic', 'lat', 'lon', 'altitude']   <- unrequested
   # after:  ['city', 'geodetic', 'lat', 'lon']
   
   # geohash_encode works on hardcoded latitude/longitude labels and maps only 
the hash
   geohash_encode(df=..., latitude="latitude", longitude="longitude", 
geohash="hash")
   # before: ['city', 'latitude', 'longitude', 'latitude', 'longitude', 'hash']
   #          columns.duplicated().any() is True, out["latitude"] is a DataFrame
   # after:  ['city', 'latitude', 'longitude', 'hash']
   ```
   
   So the duplicate-label failure is not confined to mixed mappings. An 
all-rename mapping reaches it too whenever `append_df` carries a column 
`base_df` already has. Both come from the same two lines.
   
   ### What changes and what does not
   
   This is a shared helper, so the exact blast radius:
   
   - **Unchanged:** every all-overwrite mapping, and every all-rename mapping 
whose `append_df` carries only mapped columns. That covers `cum`, `rolling` and 
`diff` in full, and geography wherever the target names match the working-frame 
names. That is what the existing tests exercise, and why all of them still pass 
untouched.
   - **Deliberately changed:** an all-rename mapping whose `append_df` is wider 
than the mapping. That is only the geography operators, and in every such case 
the dropped columns were either unrequested or duplicates. This is the second 
fix above, not a side effect.
   - **Preserved explicitly:** an empty mapping still returns `base_df.copy()` 
rather than `base_df` itself. `cum` normalizes a missing mapping to `{}`, so 
that path is reachable, and my first draft of the split would have returned the 
input object. There is a test for it.
   
   ### BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF
   
   N/A: no UI change.
   
   ### TESTING INSTRUCTIONS
   
   ```bash
   pytest tests/unit_tests/pandas_postprocessing/
   ```
   
   Six tests are added:
   
   | test | covers | on master |
   |---|---|---|
   | `test_append_columns_with_mixed_mapping` | all three mapping shapes | 
**fails** |
   | `test_append_columns_ignores_unmapped_columns` | unmapped column dropped | 
**fails** |
   | `test_append_columns_with_empty_mapping_returns_a_copy` | empty mapping 
still copies | passes |
   | `test_cum_with_mixed_column_mapping` | defect end-to-end through `cum` on 
MultiIndex columns | **fails** |
   | `test_geodetic_parse_without_altitude_drops_unasked_column` | the 
`altitude` leak, end-to-end | **fails** |
   | `test_geohash_encode_drops_working_columns` | the duplicate-label leak, 
end-to-end | **fails** |
   
   Five fail on master and pass with this change. The sixth passes on master by 
design: it guards the empty-mapping behaviour this refactor could otherwise 
have regressed, so it is a preservation test rather than a bug repro.
   
   The whole `tests/unit_tests/pandas_postprocessing/` suite goes from 180 to 
186 passing with no existing test modified, and 
`tests/unit_tests/{pandas_postprocessing,models,semantic_layers,common,charts}` 
run clean at 2197 passed, 2 xfailed (both pre-existing). `ruff check`, `ruff 
format --check` and `mypy` are clean, and `pylint` rates the changed source 
file 10.00/10.
   
   ### ADDITIONAL INFORMATION
   
   - [x] Has associated issue: Fixes #45017
   - [ ] Required feature flags:
   - [ ] Changes UI
   - [ ] Includes DB Migration (follow approval process in 
[SIP-59](https://github.com/apache/superset/issues/13351))
     - [ ] Migration is atomic, supports rollback & is backwards-compatible
     - [ ] Confirm DB migration upgrade and downgrade tested
     - [ ] Runtime estimates and downtime expectations provided
   - [ ] Introduces new feature or API
   - [ ] Removes existing feature or API
   


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