Skip to content

fix: strip underscore prefix from digit-starting codes in all serialization paths#100

Closed
ktrufanov-skycop wants to merge 1 commit intopunitarani:mainfrom
ktrufanov-skycop:fix/serialization-underscore
Closed

fix: strip underscore prefix from digit-starting codes in all serialization paths#100
ktrufanov-skycop wants to merge 1 commit intopunitarani:mainfrom
ktrufanov-skycop:fix/serialization-underscore

Conversation

@ktrufanov-skycop
Copy link
Copy Markdown
Contributor

@ktrufanov-skycop ktrufanov-skycop commented Mar 31, 2026

Summary

Follow-up to #90 (merged). Addresses the serialization gap flagged
by @punitarani in the review comment
digit-prefixed airline codes like _3F were still leaking into API
requests and CLI output through paths not covered by the first PR.

Changes

  • removeprefix("_") in flights.py and dates.py serialize()
    functions — strip the synthetic underscore before sending codes to
    Google Flights API
  • serialize_airline() in cli/utils.py — same fix for CLI JSON output
  • Round-trip selected_flight in flights.py — pass enum objects
    (leg.airline, leg.departure_airport, leg.arrival_airport) to
    serialize() instead of pre-resolving .name, which bypassed the
    isinstance check and leaked _3F into the request payload
  • Test for serialize_airline() with numeric-prefix code

Why removeprefix over lstrip

lstrip("_") would strip all leading underscores (__3F3F).
removeprefix("_") removes exactly one — matching the single underscore
added by generate_enums.py for digit-starting IATA codes.

Test plan

  • serialize_airline(Airline._3F) returns {"code": "3F", "name": "FlyOne Armenia"}
  • All 6 airline-related tests pass
  • No regressions in existing tests

Greptile Summary

This PR completes the fix for digit-prefixed IATA airline codes (e.g., _3F) leaking out of serialization paths, following up on #90. It applies removeprefix(\"_\") in the two Google Flights API serializers (FlightSearchFilters and DateSearchFilters), in the CLI JSON output helper (serialize_airline), and — critically — fixes the selected_flight round-trip block in flights.py that was passing .name strings directly to serialize(), bypassing the isinstance(obj, Airline) branch entirely.

  • fli/models/google_flights/flights.py: removeprefix(\"_\") added to serialize(), plus leg.departure_airport, leg.arrival_airport, and leg.airline now passed as enum objects (not pre-resolved .name strings) in the selected_flights builder — this was the root cause of the payload leak.
  • fli/models/google_flights/dates.py: Same removeprefix(\"_\") fix applied to the parallel serialize() in DateSearchFilters.format().
  • fli/cli/utils.py: serialize_airline() now strips the underscore from the code key in CLI JSON output.
  • tests/cli/test_utils.py: New test_serialize_airline_numeric_prefix test verifies Airline._3F{\"code\": \"3F\", \"name\": \"FlyOne Armenia\"}.
  • Minor inconsistency: fli/mcp/server.py line 294 still uses lstrip(\"_\") for airline_code, which differs from the removeprefix(\"_\") approach used everywhere else after this PR. This is a pre-existing gap not introduced here, but worth aligning.

Confidence Score: 5/5

Safe to merge — all serialization paths that send data to the Google Flights API or emit CLI/JSON output are correctly fixed.

All changed code is correct. The critical root-cause fix (passing enum objects instead of pre-resolved .name strings in the selected_flights block) is sound. The only remaining gap is a pre-existing lstrip("_") in the MCP server that is not introduced by this PR and is P2 only.

fli/mcp/server.py line 294 — pre-existing lstrip("_") inconsistency worth aligning with the removeprefix("_") approach used everywhere else after this PR.

Important Files Changed

Filename Overview
fli/models/google_flights/flights.py Two fixes: removeprefix("_") in serialize() for Airport/Airline enums, and passing enum objects (not .name strings) to serialize() in the selected_flights block — closing the bypass of the isinstance check that leaked _3F into API payloads.
fli/models/google_flights/dates.py Same removeprefix("_") fix applied to the parallel serialize() function inside DateSearchFilters.format(); no selected-flight block in this model so no further changes needed.
fli/cli/utils.py serialize_airline() updated to strip the synthetic underscore from the code key in CLI JSON output; serialize_airport() is unchanged (correct, as Airport has no digit-starting codes).
tests/cli/test_utils.py New test_serialize_airline_numeric_prefix test verifies that Airline._3F round-trips to {"code": "3F", "name": "FlyOne Armenia"} via serialize_airline().

Sequence Diagram

sequenceDiagram
    participant User
    participant Serializer
    participant GoogleFlightsAPI

    Note over User,GoogleFlightsAPI: Before PR — digit-prefix leak
    User->>Serializer: leg.airline.name passes string "_3F"
    Note over Serializer: No isinstance match, falls through
    Serializer->>GoogleFlightsAPI: payload contains "_3F" (incorrect)

    Note over User,GoogleFlightsAPI: After PR — correct round-trip
    User->>Serializer: leg.airline passes Airline enum object
    Note over Serializer: isinstance(obj, Airline) matches
    Serializer->>GoogleFlightsAPI: obj.name.removeprefix returns "3F" (correct)
Loading

Comments Outside Diff (1)

  1. fli/mcp/server.py, line 294 (link)

    P2 Inconsistent strip method vs. the rest of the codebase

    The MCP server still uses lstrip("_") here, while every other serialization path in this PR (and the PR description itself) explicitly prefers removeprefix("_") — because lstrip("_") would strip all leading underscores (e.g., a hypothetical __3F3F), whereas removeprefix("_") removes exactly the one underscore added by generate_enums.py.

    For parity with the rest of the codebase after this PR:

    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: fli/mcp/server.py
    Line: 294
    
    Comment:
    **Inconsistent strip method vs. the rest of the codebase**
    
    The MCP server still uses `lstrip("_")` here, while every other serialization path in this PR (and the PR description itself) explicitly prefers `removeprefix("_")` — because `lstrip("_")` would strip *all* leading underscores (e.g., a hypothetical `__3F``3F`), whereas `removeprefix("_")` removes exactly the one underscore added by `generate_enums.py`.
    
    For parity with the rest of the codebase after this PR:
    
    
    
    How can I resolve this? If you propose a fix, please make it concise.
Prompt To Fix All With AI
This is a comment left during a code review.
Path: fli/mcp/server.py
Line: 294

Comment:
**Inconsistent strip method vs. the rest of the codebase**

The MCP server still uses `lstrip("_")` here, while every other serialization path in this PR (and the PR description itself) explicitly prefers `removeprefix("_")` — because `lstrip("_")` would strip *all* leading underscores (e.g., a hypothetical `__3F``3F`), whereas `removeprefix("_")` removes exactly the one underscore added by `generate_enums.py`.

For parity with the rest of the codebase after this PR:

```suggestion
        "airline_code": getattr(leg.airline, "name", str(leg.airline)).removeprefix("_"),
```

How can I resolve this? If you propose a fix, please make it concise.

Reviews (1): Last reviewed commit: "fix: strip underscore prefix from digit-..." | Re-trigger Greptile

(4/5) You can add custom instructions or style guidelines for the agent here!

…ization

  paths

  - Use removeprefix("_") instead of lstrip("_") for safer single-prefix
  removal
  - Fix date search serialization in dates.py (was still sending _3F to API)
  - Fix round-trip selected_flight serialization in flights.py: pass enum
    objects to serialize() instead of pre-resolving .name (which bypassed
    the prefix-stripping logic)
  - Add test for serialize_airline with numeric-prefix code
@ktrufanov-skycop
Copy link
Copy Markdown
Contributor Author

Duplicate — resolved conflict in #94 instead.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant