Skip to content

Commit

Permalink
FIX: incorrect Ergast API paths in some edge cases (#489)
Browse files Browse the repository at this point in the history
  • Loading branch information
Lombardoc4 authored Dec 26, 2023
1 parent aef3668 commit 3474b03
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 28 deletions.
53 changes: 36 additions & 17 deletions fastf1/ergast/interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@ class ErgastRawResponse(ErgastResponseMixin, list):
auto_cast: Determines if values are automatically cast to the most
appropriate data type from their original string representation
"""

def __init__(self, *, query_result, category, auto_cast, **kwargs):
if auto_cast:
query_result = self._prepare_response(query_result, category)
Expand Down Expand Up @@ -351,6 +352,7 @@ class ErgastMultiResponse(ErgastResponseMixin):
auto_cast: Flag that enables or disables automatic casting from the
original string representation to the most suitable data type.
"""

def __init__(self, *args,
response_description: dict,
response_data: list,
Expand Down Expand Up @@ -409,6 +411,7 @@ class Ergast:
30 if not set. Maximum: 1000. See also "Response Paging" on
https://ergast.com/mrd/.
"""

def __init__(self,
result_type: Literal['raw', 'pandas'] = 'pandas',
auto_cast: bool = True,
Expand Down Expand Up @@ -439,41 +442,57 @@ def _build_url(
selectors.append(f"/{season}")
if round is not None:
selectors.append(f"/{round}")
if circuit is not None:
selectors.append(f"/circuits/{circuit}")
if constructor is not None:
selectors.append(f"/constructors/{constructor}")
if driver is not None:
selectors.append(f"/drivers/{driver}")
if grid_position is not None:
selectors.append(f"/grid/{grid_position}")
if results_position is not None:
selectors.append(f"/results/{results_position}")
if fastest_rank is not None:
selectors.append(f"/fastest/{fastest_rank}")
if status is not None:
selectors.append(f"/status/{status}")

# some special cases: the endpoint may also be used as selector
# therefore, if the specifier is defined, do not add the endpoint
# string additionally
if driver is not None:
if endpoint == 'drivers':
endpoint = f"drivers/{driver}"
else:
selectors.append(f"/drivers/{driver}")

if constructor is not None:
if endpoint == 'constructors':
endpoint = f"constructors/{constructor}"
else:
selectors.append(f"/constructors/{constructor}")

if circuit is not None:
if endpoint == 'circuits':
endpoint = f"circuits/{circuit}"
else:
selectors.append(f"/circuits/{circuit}")

if status is not None:
if endpoint == 'status':
endpoint = f"status/{status}"
else:
selectors.append(f"/status/{status}")

if standings_position is not None:
if endpoint == 'driverStandings':
selectors.append(f"/driverStandings/{standings_position}")
endpoint = None
endpoint = f"driverStandings/{standings_position}"
elif endpoint == 'constructorStandings':
selectors.append(f"/constructorStandings/{standings_position}")
endpoint = None
endpoint = f"constructorStandings/{standings_position}"

if lap_number is not None:
selectors.append(f"/laps/{lap_number}")
if endpoint == 'laps':
endpoint = None
endpoint = f"laps/{lap_number}"
else:
selectors.append(f"/laps/{lap_number}")

if stop_number is not None:
selectors.append(f"/pitstops/{stop_number}")
if endpoint == 'pitstops':
endpoint = None
endpoint = f"pitstops/{stop_number}"
else:
selectors.append(f"/pitstops/{stop_number}")

if endpoint is not None:
selectors.append(f"/{endpoint}")
Expand Down Expand Up @@ -845,7 +864,7 @@ def get_constructor_info(
'fastest_rank': fastest_rank,
'status': status}

return self._build_default_result(endpoint='constructors',
return self._build_default_result(endpoint="constructors",
table='ConstructorTable',
category=API.Constructors,
subcategory=None,
Expand Down
70 changes: 59 additions & 11 deletions fastf1/tests/test_ergast.py
Original file line number Diff line number Diff line change
Expand Up @@ -313,30 +313,78 @@ def test_merge_dicts_of_lists(data, expected):
@pytest.mark.parametrize(
"endpoint, selectors, expected",
(
# "normal" behaviour for most endpoints
# "simple" behaviour
['seasons', {}, "https://ergast.com/api/f1/seasons.json"],
['circuits', {'driver': 'alonso', 'constructor': 'alpine'},
"https://ergast.com/api/f1/constructors/alpine/"
"drivers/alonso/circuits.json"],
['races', {'season': 2022},
"https://ergast.com/api/f1/2022/races.json"],
['results', {'season': 2022, 'round': '10'},
"https://ergast.com/api/f1/2022/10/results.json"],
['sprint', {'season': 2022, 'round': '4'},
"https://ergast.com/api/f1/2022/4/sprint.json"],
['qualifying', {'season': 2022, 'round': '10'},
"https://ergast.com/api/f1/2022/10/qualifying.json"],
# special cases where endpoint name matches selector and the endpoint
# gets extended with its selection
['drivers', {},
"https://ergast.com/api/f1/drivers.json"],
['drivers', {'driver': 'alonso'},
"https://ergast.com/api/f1/drivers/alonso.json"],
['constructors', {},
"https://ergast.com/api/f1/constructors.json"],
['constructors', {'constructor': 'ferrari'},
"https://ergast.com/api/f1/constructors/ferrari.json"],
['circuits', {},
"https://ergast.com/api/f1/circuits.json"],
['circuits', {'circuit': 'monza'},
"https://ergast.com/api/f1/circuits/monza.json"],
['status', {},
"https://ergast.com/api/f1/status.json"],
['status', {'status': '1'},
"https://ergast.com/api/f1/status/1.json"],
['driverStandings', {'season': 2022},
"https://ergast.com/api/f1/2022/driverStandings.json"],
['driverStandings', {'season': 2022, 'standings_position': '1'},
"https://ergast.com/api/f1/2022/driverStandings/1.json"],
['constructorStandings', {'season': 2022},
"https://ergast.com/api/f1/2022/constructorStandings.json"],
['constructorStandings', {'season': 2022, 'standings_position': '1'},
"https://ergast.com/api/f1/2022/constructorStandings/1.json"],
# special case where endpoint name matches selector
['laps', {'season': 2022, 'round': 10},
"https://ergast.com/api/f1/2022/10/laps.json"],
['laps', {'season': 2022, 'round': 10, 'lap_number': 1},
"https://ergast.com/api/f1/2022/10/laps/1.json"],
['pitstops', {'season': 2022, 'round': 10},
"https://ergast.com/api/f1/2022/10/pitstops.json"],
['pitstops', {'season': 2022, 'round': 10, 'stop_number': '1'},
"https://ergast.com/api/f1/2022/10/pitstops/1.json"],
# endpoint/selector combination in other request
['pitstops', {'season': 2022, 'round': 10, 'lap_number': 1},
"https://ergast.com/api/f1/2022/10/laps/1/pitstops.json"],
# combined selector standings_position
['driverStandings', {'season': 2022, 'standings_position': 1},
"https://ergast.com/api/f1/2022/driverStandings/1.json"],
['constructorStandings', {'season': 2022, 'standings_position': 3},
"https://ergast.com/api/f1/2022/constructorStandings/3.json"]
['circuits', {'driver': 'alonso', 'constructor': 'alpine'},
"https://ergast.com/api/f1/drivers/alonso/"
"constructors/alpine/circuits.json"],
)
)
def test_ergast_build_url(endpoint: str, selectors: dict, expected: str):
Expand Down

0 comments on commit 3474b03

Please sign in to comment.