Skip to content

Commit

Permalink
FIX: driver info parser may return incomplete data (fixes #460)
Browse files Browse the repository at this point in the history
  • Loading branch information
theOehrly committed Oct 7, 2023
1 parent 317bacf commit e1bb85b
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 50 deletions.
13 changes: 13 additions & 0 deletions docs/changelog/v3.1.x.rst
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
What's new in v3.1.3
--------------------

(released 07/10/2023)

Bug Fixes
^^^^^^^^^

- fixed a bug in the driver list parser that caused Piastri to be missing from
the results in the 2023 Qatar Sprint Shootout (#460)



What's new in v3.1.2
--------------------

Expand Down
68 changes: 24 additions & 44 deletions fastf1/_api.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import base64
import collections
import datetime
import json
import zlib
Expand Down Expand Up @@ -1487,51 +1488,30 @@ def driver_info(path, response=None, livedata=None):
"recently, please try again in a few minutes."
)

# search for the correct entries that contain driver/team/headshot info
# for some sessions headshots are one entry for each team (Miami 22 FPs, Q)
drv_idx = None
team_idx = None
headshots = []

for i, entry in enumerate(response):
if 'RacingNumber' in str(entry):
drv_idx = i
if 'TeamName' in str(entry):
team_idx = i
if 'HeadshotUrl' in str(entry):
headshots.append(i)
if drv_idx and team_idx:
break

# parse data
try:
drv_info = response[drv_idx][1]
except (IndexError, TypeError):
return dict()

try:
team_info = response[team_idx][1]
except (IndexError, TypeError):
return dict()

# loop through headshots
try:
head_info = dict()
for head in headshots:
head_info.update(response[head][1])
except (IndexError, TypeError):
return dict()
drivers = collections.defaultdict(dict)

else:
for drv in drv_info:
drv_info[drv].update(team_info.get(drv, {}))
drv_info[drv].update(head_info.get(drv, {}))

if not len(drv_info) or not isinstance(drv_info, dict):
return dict()
if 'RacingNumber' not in list(drv_info.values())[0]:
return dict()
return drv_info
default_keys = [
'RacingNumber', 'BroadcastName', 'FullName', 'Tla', 'Line', 'TeamName',
'TeamColour', 'FirstName', 'LastName', 'Reference', 'HeadshotUrl'
]

for line in response:
try:
ts, content = line
except ValueError:
# unexpected data format, incorrect number of values to unpack
continue
if not isinstance(content, dict):
continue # unexpected data format
for drv_num, patch in content.items():
if not isinstance(patch, dict):
continue # unexpected data format
for key, val in patch.items():
if key not in default_keys:
continue
drivers[drv_num][key] = val

return drivers


@Cache.api_request_wrapper
Expand Down
2 changes: 1 addition & 1 deletion fastf1/req.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ class Cache:
"""
_CACHE_DIR = None
# version of the api parser code (unrelated to release version number)
_API_CORE_VERSION = 11
_API_CORE_VERSION = 12
_IGNORE_VERSION = False
_FORCE_RENEW = False

Expand Down
11 changes: 6 additions & 5 deletions fastf1/tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -240,12 +240,13 @@ def test_driver_list():
# ########## verify driver data
assert isinstance(data, dict)
assert len(data.keys()) == 20
dtypes = [str, str, str, str, int, str, str, str, str, str, str,
datetime.timedelta, datetime.timedelta, datetime.timedelta,
datetime.timedelta, str, float]
dtypes = {'RacingNumber': str, 'BroadcastName': str, 'FullName': str,
'Tla': str, 'Line': int, 'TeamName': str, 'TeamColour': str,
'FirstName': str, 'LastName': str, 'Reference': str,
'HeadshotUrl': str}
for driver in data.values():
for col, dtype in zip(driver.values(), dtypes):
assert isinstance(col, dtype)
for key, val in driver.items():
assert isinstance(val, dtypes[key])


# ########## special test cases ##########
Expand Down

0 comments on commit e1bb85b

Please sign in to comment.