Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions fastf1/_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -892,10 +892,10 @@ def timing_app_data(path, response=None, livedata=None):
row = entry[1]
for driver_number in row['Lines']:
if update := recursive_dict_get(row, 'Lines', driver_number, 'Stints'):
for stint_number, stint in enumerate(update):
if isinstance(update, dict):
stint_number = int(stint)
stint = update[stint]
if isinstance(update, list):
update = {str(i): s for i, s in enumerate(update)}
for stint_number, stint in update.items():
stint_number = int(stint_number)
for key in data:
if key in stint:
val = stint[key]
Expand Down
62 changes: 62 additions & 0 deletions fastf1/tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,68 @@ def test_driver_list_contains_support_race(caplog):
_, _, warn_message = caplog.record_tuples[0]
assert warn_message.startswith("Skipping delayed declaration of driver")

def test_timing_app_data_legacy_list_format():
"""Stints in list format (legacy API, ~2018-2019) must be parsed correctly.

Historic races return stints as a plain list instead of a dict with
string indices. Previously, this caused stints to be silently dropped.
See issue #863.
"""
response = [
[
"00:05:00:000",
{
"Lines": {
"1": {
"Stints": [
{"Compound": "SOFT", "New": "true",
"TotalLaps": 0, "StartLaps": 0},
{"Compound": "HARD", "New": "false",
"TotalLaps": 10, "StartLaps": 10},
]
}
}
}
]
]

data = fastf1._api.timing_app_data('api/path', response=response)

assert isinstance(data, pd.DataFrame)
assert len(data) == 2 # both stints must be present
assert list(data['Stint']) == [0, 1]
assert list(data['Compound']) == ['SOFT', 'HARD']
assert list(data['Driver']) == ['1', '1']


def test_timing_app_data_modern_dict_format():
"""Stints in dict format (modern API) must continue to work correctly."""
response = [
[
"00:05:00:000",
{
"Lines": {
"1": {
"Stints": {
"0": {"Compound": "MEDIUM", "New": "true",
"TotalLaps": 0, "StartLaps": 0},
"1": {"Compound": "HARD", "New": "false",
"TotalLaps": 20, "StartLaps": 20},
}
}
}
}
]
]

data = fastf1._api.timing_app_data('api/path', response=response)

assert isinstance(data, pd.DataFrame)
assert len(data) == 2 # both stints must be present
assert list(data['Stint']) == [0, 1]
assert list(data['Compound']) == ['MEDIUM', 'HARD']
assert list(data['Driver']) == ['1', '1']

@pytest.mark.f1telapi
def test_deleted_laps_not_marked_personal_best():
# see issue #165
Expand Down