Pylint added and changes reflected throughout

This commit is contained in:
Samuel Roach 2022-06-06 01:58:53 +01:00
parent 4ef3c06c15
commit 2a524596f9
25 changed files with 1281 additions and 776 deletions

5
.pylintrc Normal file
View File

@ -0,0 +1,5 @@
[MASTER]
disable=too-many-instance-attributes,
too-many-arguments,
too-many-locals

View File

@ -146,7 +146,7 @@ More detail on the available functions within the ``Ergast()`` class is availabl
<summary><b>RETURN</b> functions</summary> <summary><b>RETURN</b> functions</summary>
</br> </br>
> NOTE: All the return types that return a single object will raise an Exception if your query is returning more than one item. > NOTE: All the functions that return a single object will raise an Exception if your query is returning more than one item.
| Name | Return Type | | Name | Return Type |
| ------------------------- | --------------------- | | ------------------------- | --------------------- |

View File

@ -1,139 +1,229 @@
""" Expected class """
class Expected(): class Expected():
""" """
Storage of the expected keys returned and their types Representations of the types expected to be found within a model.
"""
location = { Each model has a set of keys, and the types expected.
"lat": "float",
"long": "float",
"locality": "string",
"country": "string",
}
circuit = { Types are stored as one of the following strings:
"circuitId": "string", * "int"
"url": "string", * "float"
"circuitName": "string", * "string"
"Location": "string", * "dict"
} """
constructor = { @property
"constructorId": "string", def location(self):
"url": "string", """
"name": "string", Return the expected types of a Location
"nationality": "string", """
} return {
"lat": "float",
"long": "float",
"locality": "string",
"country": "string",
}
driver = { @property
"driverId": "string", def circuit(self):
"permanentNumber": "int", """
"code": "string", Return the expected types of a Circuit
"url": "string", """
"givenName": "string", return {
"familyName": "string", "circuitId": "string",
"dateOfBirth": "string", "url": "string",
"nationality": "string", "circuitName": "string",
} "Location": "string",
}
race = { @property
"season": "int", def constructor(self):
"round": "int", """
"url": "string", Return the expected types of a Constructor
"raceName": "string", """
"Circuit": "dict", return {
"date": "string", "constructorId": "string",
"time": "string", "url": "string",
"Results": "dict", "name": "string",
"FirstPractice": "dict", "nationality": "string",
"SecondPractice": "dict", }
"ThirdPractice": "dict",
"Sprint": "dict",
"SprintResults": "dict",
"Qualifying": "dict",
"QualifyingResults": "dict",
"PitStops": "dict",
"Laps": "dict",
}
result = { @property
"number": "int", def driver(self):
"position": "int", """
"positionText": "string", Return the expected types of a Driver
"points": "float", """
"Driver": "dict", return {
"Constructor": "dict", "driverId": "string",
"grid": "int", "permanentNumber": "int",
"laps": "int", "code": "string",
"status": "string", "url": "string",
"Time": "dict", "givenName": "string",
"FastestLap": "dict", "familyName": "string",
"Q1": "string", "dateOfBirth": "string",
"Q2": "string", "nationality": "string",
"Q3": "string", }
}
fastest_lap = { @property
"rank": "int", def race(self):
"lap": "int", """
"Time": "dict", Return the expected types of a Race
"AverageSpeed": "dict", """
} return {
"season": "int",
"round": "int",
"url": "string",
"raceName": "string",
"Circuit": "dict",
"date": "string",
"time": "string",
"Results": "dict",
"FirstPractice": "dict",
"SecondPractice": "dict",
"ThirdPractice": "dict",
"Sprint": "dict",
"SprintResults": "dict",
"Qualifying": "dict",
"QualifyingResults": "dict",
"PitStops": "dict",
"Laps": "dict",
}
average_speed = { @property
"units": "string", def result(self):
"speed": "float", """
} Return the expected types of a Result
"""
return {
"number": "int",
"position": "int",
"positionText": "string",
"points": "float",
"Driver": "dict",
"Constructor": "dict",
"grid": "int",
"laps": "int",
"status": "string",
"Time": "dict",
"FastestLap": "dict",
"Q1": "string",
"Q2": "string",
"Q3": "string",
}
pit_stop = { @property
"driverId": "string", def fastest_lap(self):
"lap": "int", """
"stop": "int", Return the expected types of a Fastest Lap
"time": "string", """
"duration": "string", return {
} "rank": "int",
"lap": "int",
"Time": "dict",
"AverageSpeed": "dict",
}
lap = { @property
"number": "int", def average_speed(self):
"Timings": "dict", """
} Return the expected types of a Average Speed
"""
return {
"units": "string",
"speed": "float",
}
timing = { @property
"driverId": "string", def pit_stop(self):
"position": "int", """
"time": "string", Return the expected types of a Pit Stop
} """
return {
"driverId": "string",
"lap": "int",
"stop": "int",
"time": "string",
"duration": "string",
}
season = { @property
"season": "int", def lap(self):
"url": "string", """
} Return the expected types of a Lap
"""
return {
"number": "int",
"Timings": "dict",
}
status = { @property
"statusId": "int", def timing(self):
"count": "int", """
"status": "string" Return the expected types of a Timing
} """
return {
"driverId": "string",
"position": "int",
"time": "string",
}
driver_standing = { @property
"position": "int", def season(self):
"positionText": "string", """
"points": "float", Return the expected types of a Season
"wins": "int", """
"Driver": "dict", return {
"Constructors": "dict" "season": "int",
} "url": "string",
}
constructor_standing = { @property
"position": "int", def status(self):
"positionText": "string", """
"points": "float", Return the expected types of a Status
"wins": "int", """
"Constructor": "dict" return {
} "statusId": "int",
"count": "int",
"status": "string"
}
standings_list = { @property
"season": "int", def driver_standing(self):
"round": "int", """
"DriverStandings": "dict", Return the expected types of a Driver Standing
"ConstructorStandings": "dict" """
} return {
"position": "int",
"positionText": "string",
"points": "float",
"wins": "int",
"Driver": "dict",
"Constructors": "dict"
}
@property
def constructor_standing(self):
"""
Return the expected types of a Constructor Standing
"""
return {
"position": "int",
"positionText": "string",
"points": "float",
"wins": "int",
"Constructor": "dict"
}
@property
def standings_list(self):
"""
Return the expected types of a Standings List
"""
return {
"season": "int",
"round": "int",
"DriverStandings": "dict",
"ConstructorStandings": "dict"
}

View File

@ -1,142 +1,294 @@
""" StatusType class """
class StatusType(): class StatusType():
""" """
A mapping of String onto the Status ID for that type Mappings between ID and Strings for StatusType
""" """
status_map = {
"": 0, @property
"Finished": 1, def string_to_id(self):
"Disqualified": 2, """
"Accident": 3, Return the map of StatusType strings to ids
"Collision": 4, """
"Engine": 5, return {
"Gearbox": 6, "": 0,
"Transmission": 7, "Finished": 1,
"Clutch": 8, "Disqualified": 2,
"Hydraulics": 9, "Accident": 3,
"Electrical": 10, "Collision": 4,
"+1 Lap": 11, "Engine": 5,
"+2 Laps": 12, "Gearbox": 6,
"+3 Laps": 13, "Transmission": 7,
"+4 Laps": 14, "Clutch": 8,
"+5 Laps": 15, "Hydraulics": 9,
"+6 Laps": 16, "Electrical": 10,
"+7 Laps": 17, "+1 Lap": 11,
"+8 Laps": 18, "+2 Laps": 12,
"+9 Laps": 19, "+3 Laps": 13,
"Spun off": 20, "+4 Laps": 14,
"Radiator": 21, "+5 Laps": 15,
"Suspension": 22, "+6 Laps": 16,
"Brakes": 23, "+7 Laps": 17,
"Differential": 24, "+8 Laps": 18,
"Overheating": 25, "+9 Laps": 19,
"Mechanical": 26, "Spun off": 20,
"Tyre": 27, "Radiator": 21,
"Driver Seat": 28, "Suspension": 22,
"Puncture": 29, "Brakes": 23,
"Driveshaft": 30, "Differential": 24,
"Retired": 31, "Overheating": 25,
"Fuel pressure": 32, "Mechanical": 26,
"Front wing": 33, "Tyre": 27,
"Water pressure": 34, "Driver Seat": 28,
"Refuelling": 35, "Puncture": 29,
"Wheel": 36, "Driveshaft": 30,
"Throttle": 37, "Retired": 31,
"Steering": 38, "Fuel pressure": 32,
"Technical": 39, "Front wing": 33,
"Electronics": 40, "Water pressure": 34,
"Broken wing": 41, "Refuelling": 35,
"Heat shield fire": 42, "Wheel": 36,
"Exhaust": 43, "Throttle": 37,
"Oil leak": 44, "Steering": 38,
"+11 Laps": 45, "Technical": 39,
"Wheel rim": 46, "Electronics": 40,
"Water leak": 47, "Broken wing": 41,
"Fuel pump": 48, "Heat shield fire": 42,
"Track rod": 49, "Exhaust": 43,
"+17 Laps": 50, "Oil leak": 44,
"Oil pressure": 51, "+11 Laps": 45,
"+13 Laps": 53, "Wheel rim": 46,
"Withdrew": 54, "Water leak": 47,
"+12 Laps": 55, "Fuel pump": 48,
"Engine fire": 56, "Track rod": 49,
"+26 Laps": 58, "+17 Laps": 50,
"Tyre puncture": 59, "Oil pressure": 51,
"Out of fuel": 60, "+13 Laps": 53,
"Wheel nut": 61, "Withdrew": 54,
"Not classified": 62, "+12 Laps": 55,
"Pneumatics": 63, "Engine fire": 56,
"Handling": 64, "+26 Laps": 58,
"Rear wing": 65, "Tyre puncture": 59,
"Fire": 66, "Out of fuel": 60,
"Wheel bearing": 67, "Wheel nut": 61,
"Physical": 68, "Not classified": 62,
"Fuel system": 69, "Pneumatics": 63,
"Oil line": 70, "Handling": 64,
"Fuel rig": 71, "Rear wing": 65,
"Launch control": 72, "Fire": 66,
"Injured": 73, "Wheel bearing": 67,
"Fuel": 74, "Physical": 68,
"Power loss": 75, "Fuel system": 69,
"Vibrations": 76, "Oil line": 70,
"107% Rule": 77, "Fuel rig": 71,
"Safety": 78, "Launch control": 72,
"Drivetrain": 79, "Injured": 73,
"Ignition": 80, "Fuel": 74,
"Did not qualify": 81, "Power loss": 75,
"Injury": 82, "Vibrations": 76,
"Chassis": 83, "107% Rule": 77,
"Battery": 84, "Safety": 78,
"Stalled": 85, "Drivetrain": 79,
"Halfshaft": 86, "Ignition": 80,
"Crankshaft": 87, "Did not qualify": 81,
"+10 Laps": 88, "Injury": 82,
"Safety concerns": 89, "Chassis": 83,
"Not restarted": 90, "Battery": 84,
"Alternator": 91, "Stalled": 85,
"Underweight": 92, "Halfshaft": 86,
"Safety belt": 93, "Crankshaft": 87,
"Oil pump": 94, "+10 Laps": 88,
"Fuel leak": 95, "Safety concerns": 89,
"Excluded": 96, "Not restarted": 90,
"Did not prequalify": 97, "Alternator": 91,
"Injection": 98, "Underweight": 92,
"Distributor": 99, "Safety belt": 93,
"Driver unwell": 100, "Oil pump": 94,
"Turbo": 101, "Fuel leak": 95,
"CV joint": 102, "Excluded": 96,
"Water pump": 103, "Did not prequalify": 97,
"Fatal accident": 104, "Injection": 98,
"Spark plugs": 105, "Distributor": 99,
"Fuel pipe": 106, "Driver unwell": 100,
"Eye injury": 107, "Turbo": 101,
"Oil pipe": 108, "CV joint": 102,
"Axle": 109, "Water pump": 103,
"Water pipe": 110, "Fatal accident": 104,
"+14 Laps": 111, "Spark plugs": 105,
"+15 Laps": 112, "Fuel pipe": 106,
"+25 Laps": 113, "Eye injury": 107,
"+18 Laps": 114, "Oil pipe": 108,
"+22 Laps": 115, "Axle": 109,
"+16 Laps": 116, "Water pipe": 110,
"+24 Laps": 117, "+14 Laps": 111,
"+29 Laps": 118, "+15 Laps": 112,
"+23 Laps": 119, "+25 Laps": 113,
"+21 Laps": 120, "+18 Laps": 114,
"Magneto": 121, "+22 Laps": 115,
"+44 Laps": 122, "+16 Laps": 116,
"+30 Laps": 123, "+24 Laps": 117,
"+19 Laps": 124, "+29 Laps": 118,
"+46 Laps": 125, "+23 Laps": 119,
"Supercharger": 126, "+21 Laps": 120,
"+20 Laps": 127, "Magneto": 121,
"+42 Laps": 128, "+44 Laps": 122,
"Engine misfire": 129, "+30 Laps": 123,
"Collision damage": 130, "+19 Laps": 124,
"Power Unit": 131, "+46 Laps": 125,
"ERS": 132, "Supercharger": 126,
"Brake duct": 135, "+20 Laps": 127,
"Seat": 136, "+42 Laps": 128,
"Damage": 137, "Engine misfire": 129,
"Debris": 138, "Collision damage": 130,
"Illness": 139, "Power Unit": 131,
} "ERS": 132,
"Brake duct": 135,
"Seat": 136,
"Damage": 137,
"Debris": 138,
"Illness": 139,
}
@property
def id_to_string(self):
"""
Return the map of StatusType ids to strings
"""
return {
0 : "",
1: "Finished",
2: "Disqualified",
3: "Accident",
4: "Collision",
5: "Engine",
6: "Gearbox",
7: "Transmission",
8: "Clutch",
9: "Hydraulics",
10: "Electrical",
11: "+1 Lap",
12: "+2 Laps",
13: "+3 Laps",
14: "+4 Laps",
15: "+5 Laps",
16: "+6 Laps",
17: "+7 Laps",
18: "+8 Laps",
19: "+9 Laps",
20: "Spun off",
21: "Radiator",
22: "Suspension",
23: "Brakes",
24: "Differential",
25: "Overheating",
26: "Mechanical",
27: "Tyre",
28: "Driver Seat",
29: "Puncture",
30: "Driveshaft",
31: "Retired",
32: "Fuel pressure",
33: "Front wing",
34: "Water pressure",
35: "Refuelling",
36: "Wheel",
37: "Throttle",
38: "Steering",
39: "Technical",
40: "Electronics",
41: "Broken wing",
42: "Heat shield fire",
43: "Exhaust",
44: "Oil leak",
45: "+11 Laps",
46: "Wheel rim",
47: "Water leak",
48: "Fuel pump",
49: "Track rod",
50: "+17 Laps",
51: "Oil pressure",
53: "+13 Laps",
54: "Withdrew",
55: "+12 Laps",
56: "Engine fire",
58: "+26 Laps",
59: "Tyre puncture",
60: "Out of fuel",
61: "Wheel nut",
62: "Not classified",
63: "Pneumatics",
64: "Handling",
65: "Rear wing",
66: "Fire",
67: "Wheel bearing",
68: "Physical",
69: "Fuel system",
70: "Oil line",
71: "Fuel rig",
72: "Launch control",
73: "Injured",
74: "Fuel",
75: "Power loss",
76: "Vibrations",
77: "107% Rule",
78: "Safety",
79: "Drivetrain",
80: "Ignition",
81: "Did not qualify",
82: "Injury",
83: "Chassis",
84: "Battery",
85: "Stalled",
86: "Halfshaft",
87: "Crankshaft",
88: "+10 Laps",
89: "Safety concerns",
90: "Not restarted",
91: "Alternator",
92: "Underweight",
93: "Safety belt",
94: "Oil pump",
95: "Fuel leak",
96: "Excluded",
97: "Did not prequalify",
98: "Injection",
99: "Distributor",
100: "Driver unwell",
101: "Turbo",
102: "CV joint",
103: "Water pump",
104: "Fatal accident",
105: "Spark plugs",
106: "Fuel pipe",
107: "Eye injury",
108: "Oil pipe",
109: "Axle",
110: "Water pipe",
111: "+14 Laps",
112: "+15 Laps",
113: "+25 Laps",
114: "+18 Laps",
115: "+22 Laps",
116: "+16 Laps",
117: "+24 Laps",
118: "+29 Laps",
119: "+23 Laps",
120: "+21 Laps",
121: "Magneto",
122: "+44 Laps",
123: "+30 Laps",
124: "+19 Laps",
125: "+46 Laps",
126: "Supercharger",
127: "+20 Laps",
128: "+42 Laps",
129: "Engine misfire",
130: "Collision damage",
131: "Power Unit",
132: "ERS",
135: "Brake duct",
136: "Seat",
137: "Damage",
138: "Debris",
139: "Illness",
}

View File

@ -1,3 +1,5 @@
""" Ergast class """
from __future__ import annotations from __future__ import annotations
from typing import Callable from typing import Callable
@ -14,9 +16,21 @@ from ergast_py.requester import Requester
from ergast_py.type_constructor import TypeConstructor from ergast_py.type_constructor import TypeConstructor
#pylint: disable=too-many-public-methods
class Ergast(): class Ergast():
""" """
Class for querying the Ergast API Ergast
~~~~~~
Class for querying the Ergast API.
Build up the queries using the available functions.
>>> e = ergast_py.Ergast()
>>> e.season(2021).round(1).driver_str("alonso")
Get the data using ``.get_xyz()`` functions.
>>> print(e.get_result())
""" """
def __init__(self) -> None: def __init__(self) -> None:
@ -26,6 +40,11 @@ class Ergast():
def reset(self) -> None: def reset(self) -> None:
"""
Reset the Ergast query building.
Should be called after a query is run to prevent forward interraction.
"""
self.params = { self.params = {
"season": None, "season": None,
"seasons": None, "seasons": None,
@ -52,74 +71,167 @@ class Ergast():
# #
def season(self, year: int="current") -> Ergast: def season(self, year: int="current") -> Ergast:
"""
Add a season to the current query
>>> e.season(2022).get_races()
"""
self.params["season"] = year self.params["season"] = year
return self return self
def round(self, round_no: int="last") -> Ergast: def round(self, round_no: int="last") -> Ergast:
"""
Add a round to the current query
>>> e.season(1999).round(3).get_circuit()
"""
self.params["round"] = round_no self.params["round"] = round_no
return self return self
def driver(self, driver: Driver) -> Ergast: def driver(self, driver: Driver) -> Ergast:
"""
Add a driver to the current query
>>> alonso = e.driver_str("alonso").get_driver()
>>> e.driver(alonso).get_results()
"""
self.params["driver"] = driver.driverId self.params["driver"] = driver.driverId
return self return self
def driver_str(self, driver: str) -> Ergast: def driver_str(self, driver: str) -> Ergast:
"""
Add a driver to the current query
>>> e.driver_str("alonso").get_driver()
"""
self.params["driver"] = driver self.params["driver"] = driver
return self return self
def constructor(self, constructor: Constructor) -> Ergast: def constructor(self, constructor: Constructor) -> Ergast:
"""
Add a constructor to the current query
>>> mercedes = e.constructor_str("mercedes").get_constructor()
>>> e.constructor(mercedes).get_constructor_standings()
"""
self.params["constructor"] = constructor.constructorId self.params["constructor"] = constructor.constructorId
return self return self
def constructor_str(self, constructor: str) -> Ergast: def constructor_str(self, constructor: str) -> Ergast:
"""
Add a constructor to the current query
>>> e.constructor_str("mercedes").get_constructor()
"""
self.params["constructor"] = constructor self.params["constructor"] = constructor
return self return self
def qualifying(self, position: int) -> Ergast: def qualifying(self, position: int) -> Ergast:
"""
Add a qualifying position to the current query
>>> e.season(2021).qualifying(1).get_drivers()
"""
self.params["qualifying"] = position self.params["qualifying"] = position
return self return self
def sprint(self, position: int) -> Ergast: def sprint(self, position: int) -> Ergast:
"""
Add a sprint result to the current query
>>> e.season(2021).sprint(3).get_sprints()
"""
self.params["sprint"] = position self.params["sprint"] = position
return self return self
def grid(self, position: int) -> Ergast: def grid(self, position: int) -> Ergast:
"""
Add a starting grid position to the current query
>>> e.season(2021).round(1).grid(1).get_result()
"""
self.params["grid"] = position self.params["grid"] = position
return self return self
def result(self, position: int) -> Ergast: def result(self, position: int) -> Ergast:
"""
Add a final result to the current query
>>> e.season(2021).round(1).result(20).get_result()
"""
self.params["result"] = position self.params["result"] = position
return self return self
def fastest(self, position: int) -> Ergast: def fastest(self, position: int) -> Ergast:
"""
Add a driver's fastest lap ranking to the current query
>>> e.season(2021).round(1).fastest(1).get_driver()
"""
self.params["fastest"] = position self.params["fastest"] = position
return self return self
def circuit(self, circuit: Circuit) -> Ergast: def circuit(self, circuit: Circuit) -> Ergast:
"""
Add a circuit to the current query
>>> silverstone = e.circuit_str("silverstone").get_circuit()
>>> e.circuit(silverstone)
"""
self.params["circuit"] = circuit.circuitId self.params["circuit"] = circuit.circuitId
return self return self
def circuit_str(self, circuit: str) -> Ergast: def circuit_str(self, circuit: str) -> Ergast:
"""
Add a circuit to the current query
>>> e.circuit_str("silverstone").get_circuit()
"""
self.params["circuit"] = circuit self.params["circuit"] = circuit
return self return self
def status(self, status: int) -> Ergast: def status(self, status: int) -> Ergast:
"""
Add a finishing status to the current query
>>> e.driver_str("alonso").status(2)
"""
self.params["status"] = status self.params["status"] = status
return self return self
def status_str(self, status: str) -> Ergast: def status_str(self, status: str) -> Ergast:
self.params["status"] = StatusType().status_map[status] """
Add a finishing status to the current query
>>> e.season(2021).round(1).status_str("Disqualified")
"""
self.params["status"] = StatusType().string_to_id[status]
return self return self
def standing(self, position: int) -> Ergast: def standing(self, position: int) -> Ergast:
"""
Add a position in the standings to the current query
>>> e.standing(1).get_driver_standings()
"""
self.params["standing"] = position self.params["standing"] = position
return self return self
def lap(self, lap_number: int) -> Ergast: def lap(self, lap_number: int) -> Ergast:
"""
Add a certain lap to the current query
>>> e.season(2021).round(1).lap(1).get_laps()
"""
self.params["lap"] = lap_number self.params["lap"] = lap_number
return self return self
def pit_stop(self, stop_number: int) -> Ergast: def pit_stop(self, stop_number: int) -> Ergast:
"""
Add a certain pit stop to the current query
>>> e.season(2021).round(1).pit_stop(1).get_pit_stops()
"""
self.params["pit_stop"] = stop_number self.params["pit_stop"] = stop_number
return self return self
@ -128,10 +240,20 @@ class Ergast():
# #
def limit(self, amount: int) -> Ergast: def limit(self, amount: int) -> Ergast:
"""
Limit the results in the current query
>>> e.season(2021).limit(2).get_drivers()
"""
self.params["limit"] = amount self.params["limit"] = amount
return self return self
def offset(self, amount: int) -> Ergast: def offset(self, amount: int) -> Ergast:
"""
Offset the results in the current query
>>> e.season(2021).limit(2).offset(4).get_drivers()
"""
self.params["offset"] = amount self.params["offset"] = amount
return self return self
@ -156,191 +278,187 @@ class Ergast():
# Race and Results Queries # Race and Results Queries
def get_circuits(self) -> list[Circuit]: def get_circuits(self) -> list[Circuit]:
return self._get_items(self.requester.get_circuits, self.type_constructor.construct_circuits) """
Get a list of circuits from the current query
"""
return self._get_items(self.requester.get_circuits,
self.type_constructor.construct_circuits)
def get_circuit(self) -> Circuit: def get_circuit(self) -> Circuit:
return self._get_item(self.requester.get_circuits, self.type_constructor.construct_circuits) """
Get a circuit from the current query
"""
return self._get_item(self.requester.get_circuits,
self.type_constructor.construct_circuits)
def get_constructors(self) -> list[Constructor]: def get_constructors(self) -> list[Constructor]:
constructors_json = self.requester.get_constructors(self.params) """
constructors = self.type_constructor.construct_constructors(constructors_json) Get a list of constructors from the current query
self.reset() """
return constructors return self._get_items(self.requester.get_constructors,
self.type_constructor.construct_constructors)
def get_constructor(self) -> Constructor: def get_constructor(self) -> Constructor:
constructors_json = self.requester.get_constructors(self.params) """
constructors = self.type_constructor.construct_constructors(constructors_json) Get a constructor from the current query
self.reset() """
if len(constructors) == 1: return self._get_item(self.requester.get_constructors,
return constructors[0] self.type_constructor.construct_constructors)
else:
raise Exception("More than 1 item found")
def get_drivers(self) -> list[Driver]: def get_drivers(self) -> list[Driver]:
drivers_json = self.requester.get_drivers(self.params) """
drivers = self.type_constructor.construct_drivers(drivers_json) Get a list of drivers from the current query
self.reset() """
return drivers return self._get_items(self.requester.get_drivers,
self.type_constructor.construct_drivers)
def get_driver(self) -> Driver: def get_driver(self) -> Driver:
drivers_json = self.requester.get_drivers(self.params) """
drivers = self.type_constructor.construct_drivers(drivers_json) Get a driver from the current query
self.reset() """
if len(drivers) == 1: return self._get_item(self.requester.get_drivers,
return drivers[0] self.type_constructor.construct_drivers)
else:
raise Exception("More than 1 item found")
def get_qualifyings(self) -> list[Race]: def get_qualifyings(self) -> list[Race]:
qualify_json = self.requester.get_qualifying(self.params) """
qualifying = self.type_constructor.construct_races(qualify_json) Get a list of qualifyings from the current query
self.reset() """
return qualifying return self._get_items(self.requester.get_qualifying,
self.type_constructor.construct_races)
def get_qualifying(self) -> Race: def get_qualifying(self) -> Race:
qualify_json = self.requester.get_qualifying(self.params) """
qualifying = self.type_constructor.construct_races(qualify_json) Get a qualifying from the current query
self.reset() """
if len(qualifying) == 1: return self._get_item(self.requester.get_qualifying,
return qualifying[0] self.type_constructor.construct_races)
else:
raise Exception("More than 1 item found")
def get_sprints(self) -> list[Race]: def get_sprints(self) -> list[Race]:
sprint_json = self.requester.get_sprints(self.params) """
sprint = self.type_constructor.construct_races(sprint_json) Get a list of sprints from the current query
self.reset() """
return sprint return self._get_items(self.requester.get_sprints,
self.type_constructor.construct_races)
def get_sprint(self) -> Race: def get_sprint(self) -> Race:
sprint_json = self.requester.get_sprints(self.params) """
sprint = self.type_constructor.construct_races(sprint_json) Get a sprint from the current query
self.reset() """
if len(sprint) == 1: return self._get_item(self.requester.get_sprints,
return sprint[0] self.type_constructor.construct_races)
else:
raise Exception("More than 1 item found")
def get_results(self) -> list[Race]: def get_results(self) -> list[Race]:
results_json = self.requester.get_results(self.params) """
results = self.type_constructor.construct_races(results_json) Get a list of results from the current query
self.reset() """
return results return self._get_items(self.requester.get_results,
self.type_constructor.construct_races)
def get_result(self) -> Race: def get_result(self) -> Race:
results_json = self.requester.get_results(self.params) """
results = self.type_constructor.construct_races(results_json) Get a result from the current query
self.reset() """
if len(results) == 1: return self._get_item(self.requester.get_results,
return results[0] self.type_constructor.construct_races)
else:
raise Exception("More than 1 item found")
def get_races(self) -> list[Race]: def get_races(self) -> list[Race]:
races_json = self.requester.get_races(self.params) """
races = self.type_constructor.construct_races(races_json) Get a list of races from the current query
self.reset() """
return races return self._get_items(self.requester.get_races,
self.type_constructor.construct_races)
def get_race(self) -> Race: def get_race(self) -> Race:
races_json = self.requester.get_races(self.params) """
races = self.type_constructor.construct_races(races_json) Get a race from the current query
self.reset() """
if len(races) == 1: return self._get_item(self.requester.get_races,
return races[0] self.type_constructor.construct_races)
else:
raise Exception("More than 1 item found")
def get_seasons(self) -> list[Season]: def get_seasons(self) -> list[Season]:
seasons_json = self.requester.get_seasons(self.params) """
seasons = self.type_constructor.construct_seasons(seasons_json) Get a list of seasons from the current query
self.reset() """
return seasons return self._get_items(self.requester.get_seasons,
self.type_constructor.construct_seasons)
def get_season(self) -> Season: def get_season(self) -> Season:
seasons_json = self.requester.get_seasons(self.params) """
seasons = self.type_constructor.construct_seasons(seasons_json) Get a season from the current query
self.reset() """
if len(seasons) == 1: return self._get_item(self.requester.get_seasons,
return seasons[0] self.type_constructor.construct_seasons)
else:
raise Exception("More than 1 item found")
def get_statuses(self) -> list[Status]: def get_statuses(self) -> list[Status]:
statuses_json = self.requester.get_statuses(self.params) """
statuses = self.type_constructor.construct_statuses(statuses_json) Get a list of statuses from the current query
self.reset() """
return statuses return self._get_items(self.requester.get_statuses,
self.type_constructor.construct_statuses)
def get_status(self) -> Status: def get_status(self) -> Status:
statuses_json = self.requester.get_statuses(self.params) """
statuses = self.type_constructor.construct_statuses(statuses_json) Get a status from the current query
self.reset() """
if len(statuses) == 1: return self._get_item(self.requester.get_statuses,
return statuses[0] self.type_constructor.construct_statuses)
else:
raise Exception("More than 1 item found")
# Standings Queries # Standings Queries
def get_driver_standings(self) -> list[StandingsList]: def get_driver_standings(self) -> list[StandingsList]:
standings_lists_json = self.requester.get_driver_standings(self.params) """
standings_lists = self.type_constructor.construct_standings_lists(standings_lists_json) Get a list of driver standings from the current query
self.reset() """
return standings_lists return self._get_items(self.requester.get_driver_standings,
self.type_constructor.construct_driver_standings)
def get_driver_standing(self) -> StandingsList: def get_driver_standing(self) -> StandingsList:
standings_lists_json = self.requester.get_driver_standings(self.params) """
standings_lists = self.type_constructor.construct_standings_lists(standings_lists_json) Get a driver standing from the current query
self.reset() """
if len(standings_lists) == 1: return self._get_item(self.requester.get_driver_standings,
return standings_lists[0] self.type_constructor.construct_driver_standings)
else:
raise Exception("More than 1 item found")
def get_constructor_standings(self) -> list[StandingsList]: def get_constructor_standings(self) -> list[StandingsList]:
standings_lists_json = self.requester.get_constructor_standings(self.params) """
standings_lists = self.type_constructor.construct_standings_lists(standings_lists_json) Get a list of constructor standings from the current query
self.reset() """
return standings_lists return self._get_items(self.requester.get_constructor_standings,
self.type_constructor.construct_constructor_standings)
def get_constructor_standing(self) -> StandingsList: def get_constructor_standing(self) -> StandingsList:
standings_lists_json = self.requester.get_constructor_standings(self.params) """
standings_lists = self.type_constructor.construct_standings_lists(standings_lists_json) Get a constructor standing from the current query
self.reset() """
if len(standings_lists) == 1: return self._get_item(self.requester.get_constructor_standings,
return standings_lists[0] self.type_constructor.construct_constructor_standings)
else:
raise Exception("More than 1 item found")
# Laps and Pit Stops Queries # Laps and Pit Stops Queries
def get_laps(self) -> list[Race]: def get_laps(self) -> list[Race]:
laps_json = self.requester.get_laps(self.params) """
laps = self.type_constructor.construct_races(laps_json) Get a list of laps from the current query
self.reset() """
return laps return self._get_items(self.requester.get_laps,
self.type_constructor.construct_races)
def get_lap(self) -> Race: def get_lap(self) -> Race:
laps_json = self.requester.get_laps(self.params) """
laps = self.type_constructor.construct_races(laps_json) Get a lap from the current query
self.reset() """
if len(laps) == 1: return self._get_item(self.requester.get_laps,
return laps[0] self.type_constructor.construct_races)
else:
raise Exception("More than 1 item found")
def get_pit_stops(self) -> list[Race]: def get_pit_stops(self) -> list[Race]:
pit_stops_json = self.requester.get_pit_stops(self.params) """
pit_stops = self.type_constructor.construct_races(pit_stops_json) Get a list of pit stops from the current query
self.reset() """
return pit_stops return self._get_items(self.requester.get_pit_stops,
self.type_constructor.construct_races)
def get_pit_stop(self) -> Race: def get_pit_stop(self) -> Race:
pit_stops_json = self.requester.get_pit_stops(self.params) """
pit_stops = self.type_constructor.construct_races(pit_stops_json) Get a pit stop from the current query
self.reset() """
if len(pit_stops) == 1: return self._get_item(self.requester.get_pit_stops,
return pit_stops[0] self.type_constructor.construct_races)
else:
raise Exception("More than 1 item found")

View File

@ -1,44 +1,84 @@
""" Helpers class """
import datetime import datetime
class Helpers: class Helpers:
"""
Helpers for the construction of models
"""
def construct_datetime_str(self, date: str, time: str) -> datetime.datetime: def construct_datetime_str(self, date: str, time: str) -> datetime.datetime:
"""
Construct a datetime.datetime from the date and time strings.
Looking for the format of ``%Y-%m-%d %H:%M:%SZ``
"""
new_datetime = datetime.datetime.strptime(f"{date} {time}", "%Y-%m-%d %H:%M:%SZ") new_datetime = datetime.datetime.strptime(f"{date} {time}", "%Y-%m-%d %H:%M:%SZ")
new_datetime = new_datetime.replace(tzinfo=datetime.timezone.utc) new_datetime = new_datetime.replace(tzinfo=datetime.timezone.utc)
return new_datetime return new_datetime
def construct_datetime_dict(self, dict: dict) -> datetime.datetime: def construct_datetime_dict(self, datetime_dict: dict) -> datetime.datetime:
if "date" not in dict or "time" not in dict: """
Construct a datetime.datetime from a dictionary.
Dictionary should contain the keys "date" and "time"
"""
if "date" not in datetime_dict or "time" not in datetime_dict:
return None return None
return self.construct_datetime_str(dict["date"], dict["time"]) return self.construct_datetime_str(datetime_dict["date"], datetime_dict["time"])
def construct_date(self, date: str) -> datetime.date: def construct_date(self, date: str) -> datetime.date:
"""
Construct a datetime.date from a date string
"""
elements = date.split("-") elements = date.split("-")
return datetime.date(year=int(elements[0]), month=int(elements[1]), day=int(elements[2])) return datetime.date(year=int(elements[0]), month=int(elements[1]), day=int(elements[2]))
def construct_lap_time_millis(self, millis: dict) -> datetime.time: def construct_lap_time_millis(self, millis: dict) -> datetime.time:
"""
Construct a datetime.time (lap time) from a dict containing the millis
"""
if "millis" in millis: if "millis" in millis:
value = int(millis["millis"]) value = int(millis["millis"])
return datetime.datetime.fromtimestamp(value/1000.0).time() return datetime.datetime.fromtimestamp(value/1000.0).time()
return None return None
def format_lap_time(self, time: str) -> datetime.time: def format_lap_time(self, time: str) -> datetime.time:
"""
Construct a datetime.time (lap time) from a time string
"""
if time != "": if time != "":
return datetime.datetime.strptime(time, "%M:%S.%f").time() return datetime.datetime.strptime(time, "%M:%S.%f").time()
return None return None
def construct_lap_time(self, time: dict) -> datetime.time: def construct_lap_time(self, time: dict) -> datetime.time:
"""
Construct a datetime.time (lap time) from a time dictionary
The dictionary should contain the key "time"
"""
if "time" in time: if "time" in time:
value = time["time"] value = time["time"]
return self.format_lap_time(value) return self.format_lap_time(value)
return None return None
def construct_local_time(self, time: str) -> datetime.time: def construct_local_time(self, time: str) -> datetime.time:
if "time" != "": """
Construct a datetime.time from a time string
Looking for the format of ``%H:%M:%S``
"""
if time != "":
return datetime.datetime.strptime(f"{time}", "%H:%M:%S").time() return datetime.datetime.strptime(f"{time}", "%H:%M:%S").time()
return None return None
def construct_pitstop_duration(self, time: str) -> datetime.time: def construct_pitstop_duration(self, time: str) -> datetime.time:
if "time" != "": """
Construct a datetime.time (pit stop duration) from a time string
Looking for the format of ``%S.%f``
"""
if time != "":
return datetime.datetime.strptime(f"{time}", "%S.%f").time() return datetime.datetime.strptime(f"{time}", "%S.%f").time()
return None return None

View File

@ -1,9 +1,15 @@
""" AverageSpeed class """
from dataclasses import dataclass from dataclasses import dataclass
from ergast_py.models.model import Model
@dataclass @dataclass
class AverageSpeed: class AverageSpeed(Model):
""" """
Representation of a Drivers Average Speed Representation of a Drivers Average Speed
Average Speeds may contain: Average Speeds may contain:
units: String units: String
speed: Float speed: Float
@ -12,12 +18,3 @@ class AverageSpeed:
def __init__(self, units: str, speed: float) -> None: def __init__(self, units: str, speed: float) -> None:
self.units = units self.units = units
self.speed = speed self.speed = speed
pass
def __str__(self) -> str:
members = ', '.join(f"{key}={value}" for key, value in self.__dict__.items())
return f"{type(self).__name__}({members})"
def __repr__(self) -> str:
members = ', '.join(f"{key}={value}" for key, value in self.__dict__.items())
return f"{type(self).__name__}({members})"

View File

@ -1,28 +1,25 @@
""" Circuit class """
from dataclasses import dataclass from dataclasses import dataclass
from ergast_py.models.location import Location from ergast_py.models.location import Location
from ergast_py.models.model import Model
@dataclass @dataclass
class Circuit: class Circuit(Model):
""" """
Representation of a Formula One Circuit Representation of a Formula One Circuit
Circuits may contain: Circuits may contain:
circuitId: String circuit_id: String
url: String url: String
circuitName: String circuit_name: String
location: Location location: Location
""" """
def __init__(self, circuitId: str, url: str, circuitName: str, location: Location) -> None: def __init__(self, circuit_id: str, url: str, circuit_name: str, location: Location) -> None:
self.circuitId = circuitId self.circuit_id = circuit_id
self.url = url self.url = url
self.circuitName = circuitName self.circuit_name = circuit_name
self.location = location self.location = location
pass
def __str__(self) -> str:
members = ', '.join(f"{key}={value}" for key, value in self.__dict__.items())
return f"{type(self).__name__}({members})"
def __repr__(self) -> str:
members = ', '.join(f"{key}={value}" for key, value in self.__dict__.items())
return f"{type(self).__name__}({members})"

View File

@ -1,27 +1,24 @@
""" Constructor class """
from dataclasses import dataclass from dataclasses import dataclass
from ergast_py.models.model import Model
@dataclass @dataclass
class Constructor: class Constructor(Model):
""" """
Representation of a Formula One Team Representation of a Formula One Team
Constructors may contain: Constructors may contain:
constructorId: String constructor_id: String
url: String url: String
name: String name: String
nationality: String nationality: String
""" """
def __init__(self, constructorId: str, url: str, name: str, nationality: str) -> None: def __init__(self, constructor_id: str, url: str, name: str, nationality: str) -> None:
self.constructorId = constructorId self.constructor_id = constructor_id
self.url = url self.url = url
self.name = name self.name = name
self.nationality = nationality self.nationality = nationality
pass
def __str__(self) -> str:
members = ', '.join(f"{key}={value}" for key, value in self.__dict__.items())
return f"{type(self).__name__}({members})"
def __repr__(self) -> str:
members = ', '.join(f"{key}={value}" for key, value in self.__dict__.items())
return f"{type(self).__name__}({members})"

View File

@ -1,31 +1,28 @@
""" ConstructorStanding class """
from dataclasses import dataclass from dataclasses import dataclass
from ergast_py.models.constructor import Constructor from ergast_py.models.constructor import Constructor
from ergast_py.models.model import Model
@dataclass @dataclass
class ConstructorStanding: class ConstructorStanding(Model):
""" """
Representation of a Formula One Constructor's standing in a Season Representation of a Formula One Constructor's standing in a Season
Constructor Standings may contain: Constructor Standings may contain:
position: Integer position: Integer
positionText: String position_text: String
points: Float points: Float
wins: Integer wins: Integer
constructor: Constructor constructor: Constructor
""" """
def __init__(self, position: int, positionText: str, points: float, wins: int, constructor: Constructor) -> None: def __init__(self, position: int, position_text: str, points: float, wins: int, #pylint: disable=too-many-arguments
constructor: Constructor) -> None:
self.position = position self.position = position
self.positionText = positionText self.position_text = position_text
self.points = points self.points = points
self.wins = wins self.wins = wins
self.constructor = constructor self.constructor = constructor
pass
def __str__(self) -> str:
members = ', '.join(f"{key}={value}" for key, value in self.__dict__.items())
return f"{type(self).__name__}({members})"
def __repr__(self) -> str:
members = ', '.join(f"{key}={value}" for key, value in self.__dict__.items())
return f"{type(self).__name__}({members})"

View File

@ -1,38 +1,34 @@
from dataclasses import dataclass """ Driver class """
from ergast_py.helpers import Helpers
import datetime import datetime
from dataclasses import dataclass
from ergast_py.models.model import Model
@dataclass @dataclass
class Driver: class Driver(Model):
""" """
Representation of a Formula One driver Representation of a Formula One driver
Drivers may contain: Drivers may contain:
driverId: String driver_id: String
permanentNumber: Integer permanent_number: Integer
code: String code: String
url: String url: String
givenName: String given_name: String
familyName: String family_name: String
dateOfBirth: datetime.date date_of_birth: datetime.date
nationality: String nationality: String
""" """
def __init__(self, driverId: str, code: str, url: str, givenName: str, familyName: str, dateOfBirth: datetime.date, def __init__(self, driver_id: str, code: str, url: str, given_name: str, family_name: str,
nationality: str, permanentNumber: int) -> None: date_of_birth: datetime.date, nationality: str, permanent_number: int) -> None:
self.driverId = driverId self.driver_id = driver_id
self.permanentNumber = permanentNumber self.permanent_number = permanent_number
self.code = code self.code = code
self.url = url self.url = url
self.givenName = givenName self.given_name = given_name
self.familyName = familyName self.family_name = family_name
self.dateOfBirth = dateOfBirth self.date_of_birth = date_of_birth
self.nationality = nationality self.nationality = nationality
pass
def __str__(self) -> str:
members = ', '.join(f"{key}={value}" for key, value in self.__dict__.items())
return f"{type(self).__name__}({members})"
def __repr__(self) -> str:
members = ', '.join(f"{key}={value}" for key, value in self.__dict__.items())
return f"{type(self).__name__}({members})"

View File

@ -1,35 +1,31 @@
from dataclasses import dataclass """ DriverStanding class """
from ergast_py.models.constructor import Constructor
from dataclasses import dataclass
from ergast_py.models.constructor import Constructor
from ergast_py.models.driver import Driver from ergast_py.models.driver import Driver
from ergast_py.models.model import Model
@dataclass @dataclass
class DriverStanding: class DriverStanding(Model):
""" """
Representation of a Formula One Driver's standing in a Season Representation of a Formula One Driver's standing in a Season
Driver Standings may contain: Driver Standings may contain:
position: Integer position: Integer
positionText: String position_text: String
points: Float points: Float
wins: Integer wins: Integer
driver: Driver driver: Driver
constructors: Constructor[] constructors: Constructor[]
""" """
def __init__(self, position: int, positionText: str, points: float, wins: int, driver: Driver, def __init__(self, position: int, position_text: str, points: float, wins: int, driver: Driver, #pylint: disable=too-many-arguments
constructors: list[Constructor]) -> None: constructors: list[Constructor]) -> None:
self.position = position self.position = position
self.positionText = positionText self.position_text = position_text
self.points = points self.points = points
self.wins = wins self.wins = wins
self.driver = driver self.driver = driver
self.constructors = constructors self.constructors = constructors
pass
def __str__(self) -> str:
members = ', '.join(f"{key}={value}" for key, value in self.__dict__.items())
return f"{type(self).__name__}({members})"
def __repr__(self) -> str:
members = ', '.join(f"{key}={value}" for key, value in self.__dict__.items())
return f"{type(self).__name__}({members})"

View File

@ -1,29 +1,27 @@
from dataclasses import dataclass """ FastestLap class """
from ergast_py.models.average_speed import AverageSpeed
import datetime import datetime
from dataclasses import dataclass
from ergast_py.models.average_speed import AverageSpeed
from ergast_py.models.model import Model
@dataclass @dataclass
class FastestLap: class FastestLap(Model):
""" """
Representation of a Fastest Lap for a Formula One Driver Representation of a Fastest Lap for a Formula One Driver
Fastest Laps may contain: Fastest Laps may contain:
rank: Integer rank: Integer
lap: Integer lap: Integer
time: datetime.time time: datetime.time
averageSpeed: AverageSpeed average_speed: AverageSpeed
""" """
def __init__(self, rank: int, lap: int, time: datetime.time, averageSpeed: AverageSpeed) -> None: def __init__(self, rank: int, lap: int, time: datetime.time,
average_speed: AverageSpeed) -> None:
self.rank = rank self.rank = rank
self.lap = lap self.lap = lap
self.time = time self.time = time
self.averageSpeed = averageSpeed self.average_speed = average_speed
pass
def __str__(self) -> str:
members = ', '.join(f"{key}={value}" for key, value in self.__dict__.items())
return f"{type(self).__name__}({members})"
def __repr__(self) -> str:
members = ', '.join(f"{key}={value}" for key, value in self.__dict__.items())
return f"{type(self).__name__}({members})"

View File

@ -1,11 +1,16 @@
""" Lap class """
from dataclasses import dataclass from dataclasses import dataclass
from ergast_py.models.model import Model
from ergast_py.models.timing import Timing from ergast_py.models.timing import Timing
@dataclass @dataclass
class Lap: class Lap(Model):
""" """
Representation of a single Lap from a Formula One race Representation of a single Lap from a Formula One race
Laps may contain: Laps may contain:
number: Integer number: Integer
timings: Timing[] timings: Timing[]
@ -14,12 +19,3 @@ class Lap:
def __init__(self, number: int, timings: list[Timing]) -> None: def __init__(self, number: int, timings: list[Timing]) -> None:
self.number = number self.number = number
self.timings = timings self.timings = timings
pass
def __str__(self) -> str:
members = ', '.join(f"{key}={value}" for key, value in self.__dict__.items())
return f"{type(self).__name__}({members})"
def __repr__(self) -> str:
members = ', '.join(f"{key}={value}" for key, value in self.__dict__.items())
return f"{type(self).__name__}({members})"

View File

@ -1,9 +1,15 @@
""" Location class """
from dataclasses import dataclass from dataclasses import dataclass
from ergast_py.models.model import Model
@dataclass @dataclass
class Location: class Location(Model):
""" """
Representation of a Location for a Formula One Circuit Representation of a Location for a Formula One Circuit
Locations may contain: Locations may contain:
lat: Float lat: Float
long: Float long: Float
@ -16,12 +22,3 @@ class Location:
self.longitude = longitude self.longitude = longitude
self.locality = locality self.locality = locality
self.country = country self.country = country
pass
def __str__(self) -> str:
members = ', '.join(f"{key}={value}" for key, value in self.__dict__.items())
return f"{type(self).__name__}({members})"
def __repr__(self) -> str:
members = ', '.join(f"{key}={value}" for key, value in self.__dict__.items())
return f"{type(self).__name__}({members})"

14
ergast_py/models/model.py Normal file
View File

@ -0,0 +1,14 @@
""" Model class """
class Model():
"""
Base class for Models within Ergast-py
"""
def __str__(self) -> str:
members = ', '.join(f"{key}={value}" for key, value in self.__dict__.items())
return f"{type(self).__name__}({members})"
def __repr__(self) -> str:
members = ', '.join(f"{key}={value}" for key, value in self.__dict__.items())
return f"{type(self).__name__}({members})"

View File

@ -1,31 +1,28 @@
from dataclasses import dataclass """ PitStop class """
import datetime import datetime
from dataclasses import dataclass
from ergast_py.models.model import Model
@dataclass @dataclass
class PitStop: class PitStop(Model):
""" """
Representation of a single Pit Stop from a Formula One race Representation of a single Pit Stop from a Formula One race
PitStops may contain: PitStops may contain:
driverId: String driver_id: String
lap: Integer lap: Integer
stop: Integer stop: Integer
localTime: datetime.datetime local_time: datetime.datetime
duration: datetime.time duration: datetime.time
""" """
def __init__(self, driverId: str, lap: int, stop: int, localTime: datetime.datetime, def __init__(self, driver_id: str, lap: int, stop: int, local_time: datetime.datetime,
duration: datetime.time) -> None: duration: datetime.time) -> None:
self.driverId = driverId self.driver_id = driver_id
self.lap = lap self.lap = lap
self.stop = stop self.stop = stop
self.localTime = localTime self.local_time = local_time
self.duration = duration self.duration = duration
pass
def __str__(self) -> str:
members = ', '.join(f"{key}={value}" for key, value in self.__dict__.items())
return f"{type(self).__name__}({members})"
def __repr__(self) -> str:
members = ', '.join(f"{key}={value}" for key, value in self.__dict__.items())
return f"{type(self).__name__}({members})"

View File

@ -1,62 +1,58 @@
from dataclasses import dataclass """ Race class """
import datetime
import datetime
from dataclasses import dataclass
from ergast_py.helpers import Helpers
from ergast_py.models.circuit import Circuit from ergast_py.models.circuit import Circuit
from ergast_py.models.lap import Lap from ergast_py.models.lap import Lap
from ergast_py.models.result import Result from ergast_py.models.model import Model
from ergast_py.models.pit_stop import PitStop from ergast_py.models.pit_stop import PitStop
from ergast_py.models.result import Result
@dataclass @dataclass
class Race: class Race(Model):
""" """
Representation of a single Race from a Formula One season Representation of a single Race from a Formula One season
Races may contain: Races may contain:
season: Integer season: Integer
round: Integer round_no: Integer
url: String url: String
raceName: String race_name: String
circuit: Circuit circuit: Circuit
date: datetime.datetime date: datetime.datetime
results: Result[] results: Result[]
firstPractice: datetime.datetime first_practice: datetime.datetime
secondPractice: datetime.datetime second_practice: datetime.datetime
thirdPractice: datetime.datetime third_practice: datetime.datetime
sprint: datetime.datetime sprint: datetime.datetime
sprintResults: Result[] sprint_results: Result[]
qualifying: datetime.datetime qualifying: datetime.datetime
qualifyingResults: Result[] qualifying_results: Result[]
pitStops: PitStop[] pit_stops: PitStop[]
laps: Lap[] laps: Lap[]
""" """
def __init__(self, season: int, round: int, url: str, raceName: str, circuit: Circuit, date: datetime.datetime, def __init__(self, season: int, round_no: int, url: str, race_name: str, circuit: Circuit,
results: list[Result], firstPractice: datetime.datetime, secondPractice: datetime.datetime, date: datetime.datetime, results: list[Result], first_practice: datetime.datetime,
thirdPractice: datetime.datetime, sprint: datetime.datetime, sprintResults: list[Result], second_practice: datetime.datetime, third_practice: datetime.datetime,
qualifying: datetime.datetime, qualifyingResults: list[Result], pitStops: list[PitStop], sprint: datetime.datetime, sprint_results: list[Result],
laps: list[Lap]) -> None: qualifying: datetime.datetime, qualifying_results: list[Result],
pit_stops: list[PitStop], laps: list[Lap]) -> None:
self.season = season self.season = season
self.round = round self.round_no = round_no
self.url = url self.url = url
self.raceName = raceName self.race_name = race_name
self.circuit = circuit self.circuit = circuit
self.date = date self.date = date
self.results = results self.results = results
self.firstPractice = firstPractice self.first_practice = first_practice
self.secondPractice = secondPractice self.second_practice = second_practice
self.thirdPractice = thirdPractice self.third_practice = third_practice
self.sprint = sprint self.sprint = sprint
self.sprintResults = sprintResults self.sprint_results = sprint_results
self.qualifying = qualifying self.qualifying = qualifying
self.qualifyingResults = qualifyingResults self.qualifying_results = qualifying_results
self.pitStops = pitStops self.pit_stops = pit_stops
self.laps = laps self.laps = laps
pass
def __str__(self) -> str:
members = ', '.join(f"{key}={value}" for key, value in self.__dict__.items())
return f"{type(self).__name__}({members})"
def __repr__(self) -> str:
members = ', '.join(f"{key}={value}" for key, value in self.__dict__.items())
return f"{type(self).__name__}({members})"

View File

@ -1,18 +1,23 @@
from dataclasses import dataclass """ Result class """
import datetime
from ergast_py.models.constructor import Constructor
import datetime
from dataclasses import dataclass
from ergast_py.models.constructor import Constructor
from ergast_py.models.driver import Driver from ergast_py.models.driver import Driver
from ergast_py.models.fastest_lap import FastestLap from ergast_py.models.fastest_lap import FastestLap
from ergast_py.models.model import Model
@dataclass @dataclass
class Result: class Result(Model):
""" """
Representation of a single Result from a Formula One race Representation of a single Result from a Formula One race
Results may contain: Results may contain:
number: Integer number: Integer
position: Integer position: Integer
positionText: String position_text: String
points: Integer points: Integer
driver: Driver driver: Driver
constructor: Constructor constructor: Constructor
@ -20,18 +25,19 @@ class Result:
laps: Integer laps: Integer
status: Integer status: Integer
time: datetime.time time: datetime.time
fastestLap: FastestLap fastest_lap: FastestLap
q1: datetime.time qual_1: datetime.time
q2: datetime.time qual_2: datetime.time
q3: datetime.time qual_3: datetime.time
""" """
def __init__(self, number: int, position: int, positionText: str, points: float, driver: Driver, def __init__(self, number: int, position: int, position_text: str, points: float,
constructor: Constructor, grid: int, laps: int, status: int, time: datetime.time, driver: Driver, constructor: Constructor, grid: int, laps: int, status: int,
fastestLap: FastestLap, q1: datetime.time, q2: datetime.time, q3: datetime.time) -> None: time: datetime.time, fastest_lap: FastestLap, qual_1: datetime.time,
qual_2: datetime.time, qual_3: datetime.time) -> None:
self.number = number self.number = number
self.position = position self.position = position
self.positionText = positionText self.position_text = position_text
self.points = points self.points = points
self.driver = driver self.driver = driver
self.constructor = constructor self.constructor = constructor
@ -39,16 +45,7 @@ class Result:
self.laps = laps self.laps = laps
self.status = status self.status = status
self.time = time self.time = time
self.fastestLap = fastestLap self.fastest_lap = fastest_lap
self.q1 = q1 self.qual_1 = qual_1
self.q2 = q2 self.qual_2 = qual_2
self.q3 = q3 self.qual_3 = qual_3
pass
def __str__(self) -> str:
members = ', '.join(f"{key}={value}" for key, value in self.__dict__.items())
return f"{type(self).__name__}({members})"
def __repr__(self) -> str:
members = ', '.join(f"{key}={value}" for key, value in self.__dict__.items())
return f"{type(self).__name__}({members})"

View File

@ -1,9 +1,15 @@
""" Season class """
from dataclasses import dataclass from dataclasses import dataclass
from ergast_py.models.model import Model
@dataclass @dataclass
class Season: class Season(Model):
""" """
Representation of a single Season in Formula One Representation of a single Season in Formula One
Seasons may contain: Seasons may contain:
season: Integer season: Integer
url: String url: String
@ -12,12 +18,3 @@ class Season:
def __init__(self, season: int, url: str) -> None: def __init__(self, season: int, url: str) -> None:
self.season = season self.season = season
self.url = url self.url = url
pass
def __str__(self) -> str:
members = ', '.join(f"{key}={value}" for key, value in self.__dict__.items())
return f"{type(self).__name__}({members})"
def __repr__(self) -> str:
members = ', '.join(f"{key}={value}" for key, value in self.__dict__.items())
return f"{type(self).__name__}({members})"

View File

@ -1,30 +1,27 @@
""" StandingsList class """
from dataclasses import dataclass from dataclasses import dataclass
from ergast_py.models.driver_standing import DriverStanding
from ergast_py.models.constructor_standing import ConstructorStanding from ergast_py.models.constructor_standing import ConstructorStanding
from ergast_py.models.driver_standing import DriverStanding
from ergast_py.models.model import Model
@dataclass @dataclass
class StandingsList: class StandingsList(Model):
""" """
Representation of a set of Standings from a time in Formula One Representation of a set of Standings from a time in Formula One
StandingsLists may contain: StandingsLists may contain:
season: Integer season: Integer
round: Integer round_no: Integer
driverStandings: DriverStanding[] driver_standings: DriverStanding[]
constructorStandings: ConstructorStanding[] constructor_standings: ConstructorStanding[]
""" """
def __init__(self, season: int, round: int, driverStandings: list[DriverStanding], def __init__(self, season: int, round_no: int, driver_standings: list[DriverStanding],
constructorStandings: list[ConstructorStanding]) -> None: constructor_standings: list[ConstructorStanding]) -> None:
self.season = season self.season = season
self.round = round self.round_no = round_no
self.driverStandings = driverStandings self.driver_standings = driver_standings
self.constructorStandings = constructorStandings self.constructor_standings = constructor_standings
pass
def __str__(self) -> str:
members = ', '.join(f"{key}={value}" for key, value in self.__dict__.items())
return f"{type(self).__name__}({members})"
def __repr__(self) -> str:
members = ', '.join(f"{key}={value}" for key, value in self.__dict__.items())
return f"{type(self).__name__}({members})"

View File

@ -1,25 +1,22 @@
""" Status class """
from dataclasses import dataclass from dataclasses import dataclass
from ergast_py.models.model import Model
@dataclass @dataclass
class Status: class Status(Model):
""" """
Representation of the finishing status of a Driver in a Race Representation of the finishing status of a Driver in a Race
Statuses may contain: Statuses may contain:
statusId: Integer status_id: Integer
count: Integer count: Integer
status: String status: String
""" """
def __init__(self, statusId: int, count: int, status: str) -> None: def __init__(self, status_id: int, count: int, status: str) -> None:
self.statusId = statusId self.status_id = status_id
self.count = count self.count = count
self.status = status self.status = status
pass
def __str__(self) -> str:
members = ', '.join(f"{key}={value}" for key, value in self.__dict__.items())
return f"{type(self).__name__}({members})"
def __repr__(self) -> str:
members = ', '.join(f"{key}={value}" for key, value in self.__dict__.items())
return f"{type(self).__name__}({members})"

View File

@ -1,26 +1,22 @@
from dataclasses import dataclass """ Timing class """
import datetime import datetime
from dataclasses import dataclass
from ergast_py.models.model import Model
@dataclass @dataclass
class Timing: class Timing(Model):
""" """
Representation of a single timing from a lap in Formula One Representation of a single timing from a lap in Formula One
Timings may contain: Timings may contain:
driverId: String driver_id: String
position: Integer position: Integer
time: datetime.time time: datetime.time
""" """
def __init__(self, driverId: str, position: int, time: datetime.time) -> None: def __init__(self, driver_id: str, position: int, time: datetime.time) -> None:
self.driverId = driverId self.driver_id = driver_id
self.position = position self.position = position
self.time = time self.time = time
pass
def __str__(self) -> str:
members = ', '.join(f"{key}={value}" for key, value in self.__dict__.items())
return f"{type(self).__name__}({members})"
def __repr__(self) -> str:
members = ', '.join(f"{key}={value}" for key, value in self.__dict__.items())
return f"{type(self).__name__}({members})"

View File

@ -1,6 +1,8 @@
import json """ Requester class """
import requests
import json
import requests
from uritemplate import URITemplate from uritemplate import URITemplate
HOST = 'https://ergast.com/api' HOST = 'https://ergast.com/api'
@ -8,15 +10,10 @@ SERIES = 'f1'
class Requester(): class Requester():
""" """
Perform requests to the Ergast API Perform requests to the Ergast API
""" """
def __init__(self) -> None:
pass
def _get_race_results_params(self, param: dict) -> dict: def _get_race_results_params(self, param: dict) -> dict:
""" Acquire only the appropriate filters for Race/Results data """
return { return {
"season": param["season"], "season": param["season"],
"round": param["round"], "round": param["round"],
@ -40,10 +37,9 @@ class Requester():
} }
def _get_race_results_criteria(self, params: dict, resource: str) -> dict: def _get_race_results_criteria(self, params: dict, resource: str) -> dict:
""" Split the data into criteria and resource for Race/Results """
criteria = [] criteria = []
for key, value in params["filters"].items(): for key, value in params["filters"].items():
if (key != resource and value != None): if (key != resource and value is not None):
criteria.append(key) criteria.append(key)
criteria.append(value) criteria.append(value)
@ -56,7 +52,6 @@ class Requester():
} }
def _get_standings_params(self, param: dict) -> dict: def _get_standings_params(self, param: dict) -> dict:
""" Acquire only the appropriate filters for Standings data """
return { return {
"season": param["season"], "season": param["season"],
"round": param["round"], "round": param["round"],
@ -72,10 +67,9 @@ class Requester():
} }
def _get_standings_criteria(self, params: dict, resource: str) -> dict: def _get_standings_criteria(self, params: dict, resource: str) -> dict:
""" Split the data into criteria and resource for standings """
criteria = [] criteria = []
for key, value in params["filters"].items(): for key, value in params["filters"].items():
if (key != "standing" and value != None): if (key != "standing" and value is not None):
criteria.append(key) criteria.append(key)
criteria.append(value) criteria.append(value)
@ -88,7 +82,6 @@ class Requester():
} }
def _get_laps_pit_stops_params(self, param: dict) -> dict: def _get_laps_pit_stops_params(self, param: dict) -> dict:
""" Acquire only the appropriate filters for Laps and Pit Stops data """
return { return {
"season": param["season"], "season": param["season"],
"round": param["round"], "round": param["round"],
@ -104,10 +97,9 @@ class Requester():
} }
def _get_laps_pit_stops_criteria(self, params: dict, resource: str) -> dict: def _get_laps_pit_stops_criteria(self, params: dict, resource: str) -> dict:
""" Split the data into criteria and resource for Laps and Pit Stops """
criteria = [] criteria = []
for key, value in params["filters"].items(): for key, value in params["filters"].items():
if (key != resource and value != None): if (key != resource and value is not None):
criteria.append(key) criteria.append(key)
criteria.append(value) criteria.append(value)
@ -120,162 +112,216 @@ class Requester():
} }
def run_request(self, season, round, criteria, resource, value=None, limit=None, offset=None) -> dict: def run_request(self, season, round_no, criteria, resource, value=None, limit=None,
""" Takes values to run the request and return a dict """ offset=None) -> dict:
"""
Takes values to run the request and return a dict
"""
url_tmpl = URITemplate('https://ergast.com/api{/series}{/season}{/round}' url_tmpl = URITemplate('https://ergast.com/api{/series}{/season}{/round}'
'{/criteria*}{/resource}{/value}.json{?limit,offset}') '{/criteria*}{/resource}{/value}.json{?limit,offset}')
url = url_tmpl.expand(host=HOST, series=SERIES, url = url_tmpl.expand(host=HOST, series=SERIES,
season=season, round=round, season=season, round=round_no,
criteria=criteria, resource=resource, criteria=criteria, resource=resource,
value=value, limit=limit, offset=offset) value=value, limit=limit, offset=offset)
response = requests.get(url) response = requests.get(url)
if response.status_code == 200: if response.status_code == 200:
return json.loads(response.text) return json.loads(response.text)
else: raise Exception(f"Failed with status code {response.status_code}. Error: {response.reason}")
raise Exception(f"Failed with status code {response.status_code}. Error: {response.reason}")
# #
# Race and Results # Race and Results
# #
def get_circuits(self, param: dict) -> dict: def get_circuits(self, param: dict) -> dict:
"""
Get the Circuits JSON from the Ergast API
"""
params = self._get_race_results_params(param) params = self._get_race_results_params(param)
filters = self._get_race_results_criteria(params, "circuits") filters = self._get_race_results_criteria(params, "circuits")
json = self.run_request(season=params["season"], round=params["round"], api_json = self.run_request(season=params["season"], round_no=params["round"],
criteria=filters["criteria"], resource=filters["resource"], value=filters["value"], criteria=filters["criteria"], resource=filters["resource"],
limit=params["paging"]["limit"], offset=params["paging"]["offset"]) value=filters["value"], limit=params["paging"]["limit"],
offset=params["paging"]["offset"])
return json["MRData"]["CircuitTable"]["Circuits"] return api_json["MRData"]["CircuitTable"]["Circuits"]
def get_constructors(self, param: dict) -> dict: def get_constructors(self, param: dict) -> dict:
"""
Get the Constructors JSON from the Ergast API
"""
params = self._get_race_results_params(param) params = self._get_race_results_params(param)
filters = self._get_race_results_criteria(params, "constructors") filters = self._get_race_results_criteria(params, "constructors")
json = self.run_request(season=params["season"], round=params["round"], api_json = self.run_request(season=params["season"], round_no=params["round"],
criteria=filters["criteria"], resource=filters["resource"], value=filters["value"], criteria=filters["criteria"], resource=filters["resource"],
limit=params["paging"]["limit"], offset=params["paging"]["offset"]) value=filters["value"], limit=params["paging"]["limit"],
offset=params["paging"]["offset"])
return json["MRData"]["ConstructorTable"]["Constructors"] return api_json["MRData"]["ConstructorTable"]["Constructors"]
def get_drivers(self, param: dict) -> dict: def get_drivers(self, param: dict) -> dict:
"""
Get the Drivers JSON from the Ergast API
"""
params = self._get_race_results_params(param) params = self._get_race_results_params(param)
filters = self._get_race_results_criteria(params, "drivers") filters = self._get_race_results_criteria(params, "drivers")
json = self.run_request(season=params["season"], round=params["round"], api_json = self.run_request(season=params["season"], round_no=params["round"],
criteria=filters["criteria"], resource=filters["resource"], value=filters["value"], criteria=filters["criteria"], resource=filters["resource"],
limit=params["paging"]["limit"], offset=params["paging"]["offset"]) value=filters["value"], limit=params["paging"]["limit"],
offset=params["paging"]["offset"])
return json["MRData"]["DriverTable"]["Drivers"] return api_json["MRData"]["DriverTable"]["Drivers"]
def get_qualifying(self, param: dict) -> dict: def get_qualifying(self, param: dict) -> dict:
"""
Get the Qualifying JSON from the Ergast API
"""
params = self._get_race_results_params(param) params = self._get_race_results_params(param)
filters = self._get_race_results_criteria(params, "qualifying") filters = self._get_race_results_criteria(params, "qualifying")
json = self.run_request(season=params["season"], round=params["round"], api_json = self.run_request(season=params["season"], round_no=params["round"],
criteria=filters["criteria"], resource=filters["resource"], value=filters["value"], criteria=filters["criteria"], resource=filters["resource"],
limit=params["paging"]["limit"], offset=params["paging"]["offset"]) value=filters["value"], limit=params["paging"]["limit"],
offset=params["paging"]["offset"])
return json["MRData"]["RaceTable"]["Races"] return api_json["MRData"]["RaceTable"]["Races"]
def get_sprints(self, param: dict) -> dict: def get_sprints(self, param: dict) -> dict:
"""
Get the Sprints JSON from the Ergast API
"""
params = self._get_race_results_params(param) params = self._get_race_results_params(param)
filters = self._get_race_results_criteria(params, "sprint") filters = self._get_race_results_criteria(params, "sprint")
json = self.run_request(season=params["season"], round=params["round"], api_json = self.run_request(season=params["season"], round_no=params["round"],
criteria=filters["criteria"], resource=filters["resource"], value=filters["value"], criteria=filters["criteria"], resource=filters["resource"],
limit=params["paging"]["limit"], offset=params["paging"]["offset"]) value=filters["value"], limit=params["paging"]["limit"],
offset=params["paging"]["offset"])
return json["MRData"]["RaceTable"]["Races"] return api_json["MRData"]["RaceTable"]["Races"]
def get_results(self, param: dict) -> dict: def get_results(self, param: dict) -> dict:
"""
Get the Results JSON from the Ergast API
"""
params = self._get_race_results_params(param) params = self._get_race_results_params(param)
filters = self._get_race_results_criteria(params, "results") filters = self._get_race_results_criteria(params, "results")
json = self.run_request(season=params["season"], round=params["round"], api_json = self.run_request(season=params["season"], round_no=params["round"],
criteria=filters["criteria"], resource=filters["resource"], value=filters["value"], criteria=filters["criteria"], resource=filters["resource"],
limit=params["paging"]["limit"], offset=params["paging"]["offset"]) value=filters["value"], limit=params["paging"]["limit"],
offset=params["paging"]["offset"])
return json["MRData"]["RaceTable"]["Races"] return api_json["MRData"]["RaceTable"]["Races"]
def get_races(self, param: dict) -> dict: def get_races(self, param: dict) -> dict:
"""
Get the Races JSON from the Ergast API
"""
params = self._get_race_results_params(param) params = self._get_race_results_params(param)
filters = self._get_race_results_criteria(params, "races") filters = self._get_race_results_criteria(params, "races")
json = self.run_request(season=params["season"], round=params["round"], api_json = self.run_request(season=params["season"], round_no=params["round"],
criteria=filters["criteria"], resource=filters["resource"], value=filters["value"], criteria=filters["criteria"], resource=filters["resource"],
limit=params["paging"]["limit"], offset=params["paging"]["offset"]) value=filters["value"], limit=params["paging"]["limit"],
offset=params["paging"]["offset"])
return json["MRData"]["RaceTable"]["Races"] return api_json["MRData"]["RaceTable"]["Races"]
def get_seasons(self, param: dict) -> dict: def get_seasons(self, param: dict) -> dict:
"""
Get the Seasons JSON from the Ergast API
"""
params = self._get_race_results_params(param) params = self._get_race_results_params(param)
filters = self._get_race_results_criteria(params, "seasons") filters = self._get_race_results_criteria(params, "seasons")
json = self.run_request(season=params["season"], round=params["round"], api_json = self.run_request(season=params["season"], round_no=params["round"],
criteria=filters["criteria"], resource=filters["resource"], value=filters["value"], criteria=filters["criteria"], resource=filters["resource"],
limit=params["paging"]["limit"], offset=params["paging"]["offset"]) value=filters["value"], limit=params["paging"]["limit"],
offset=params["paging"]["offset"])
return json["MRData"]["SeasonTable"]["Seasons"] return api_json["MRData"]["SeasonTable"]["Seasons"]
def get_statuses(self, param: dict) -> dict: def get_statuses(self, param: dict) -> dict:
"""
Get the Statuses JSON from the Ergast API
"""
params = self._get_race_results_params(param) params = self._get_race_results_params(param)
filters = self._get_race_results_criteria(params, "status") filters = self._get_race_results_criteria(params, "status")
json = self.run_request(season=params["season"], round=params["round"], api_json = self.run_request(season=params["season"], round_no=params["round"],
criteria=filters["criteria"], resource=filters["resource"], value=filters["value"], criteria=filters["criteria"], resource=filters["resource"],
limit=params["paging"]["limit"], offset=params["paging"]["offset"]) value=filters["value"], limit=params["paging"]["limit"],
offset=params["paging"]["offset"])
return json["MRData"]["StatusTable"]["Status"] return api_json["MRData"]["StatusTable"]["Status"]
# #
# Standings # Standings
# #
def get_driver_standings(self, param: dict) -> dict: def get_driver_standings(self, param: dict) -> dict:
"""
Get the Driver Standings JSON from the Ergast API
"""
params = self._get_standings_params(param) params = self._get_standings_params(param)
filters = self._get_standings_criteria(params, "driverStandings") filters = self._get_standings_criteria(params, "driverStandings")
json = self.run_request(season=params["season"], round=params["round"], api_json = self.run_request(season=params["season"], round_no=params["round"],
criteria=filters["criteria"], resource=filters["resource"], value=filters["value"], criteria=filters["criteria"], resource=filters["resource"],
limit=params["paging"]["limit"], offset=params["paging"]["offset"]) value=filters["value"], limit=params["paging"]["limit"],
offset=params["paging"]["offset"])
return json["MRData"]["StandingsTable"]["StandingsLists"] return api_json["MRData"]["StandingsTable"]["StandingsLists"]
def get_constructor_standings(self, param: dict) -> dict: def get_constructor_standings(self, param: dict) -> dict:
"""
Get the Constructor Standings JSON from the Ergast API
"""
params = self._get_standings_params(param) params = self._get_standings_params(param)
filters = self._get_standings_criteria(params, "constructorStandings") filters = self._get_standings_criteria(params, "constructorStandings")
json = self.run_request(season=params["season"], round=params["round"], api_json = self.run_request(season=params["season"], round_no=params["round"],
criteria=filters["criteria"], resource=filters["resource"], value=filters["value"], criteria=filters["criteria"], resource=filters["resource"],
limit=params["paging"]["limit"], offset=params["paging"]["offset"]) value=filters["value"], limit=params["paging"]["limit"],
offset=params["paging"]["offset"])
return json["MRData"]["StandingsTable"]["StandingsLists"] return api_json["MRData"]["StandingsTable"]["StandingsLists"]
# #
# Laps and Pit Stops # Laps and Pit Stops
# #
def get_laps(self, param: dict) -> dict: def get_laps(self, param: dict) -> dict:
"""
Get the Laps JSON from the Ergast API
"""
params = self._get_laps_pit_stops_params(param) params = self._get_laps_pit_stops_params(param)
filters = self._get_laps_pit_stops_criteria(params, "laps") filters = self._get_laps_pit_stops_criteria(params, "laps")
json = self.run_request(season=params["season"], round=params["round"], api_json = self.run_request(season=params["season"], round_no=params["round"],
criteria=filters["criteria"], resource=filters["resource"], value=filters["value"], criteria=filters["criteria"], resource=filters["resource"],
limit=params["paging"]["limit"], offset=params["paging"]["offset"]) value=filters["value"], limit=params["paging"]["limit"],
offset=params["paging"]["offset"])
return json["MRData"]["RaceTable"]["Races"] return api_json["MRData"]["RaceTable"]["Races"]
def get_pit_stops(self, param: dict) -> dict: def get_pit_stops(self, param: dict) -> dict:
"""
Get the Pit Stops JSON from the Ergast API
"""
params = self._get_laps_pit_stops_params(param) params = self._get_laps_pit_stops_params(param)
filters = self._get_laps_pit_stops_criteria(params, "pitstops") filters = self._get_laps_pit_stops_criteria(params, "pitstops")
json = self.run_request(season=params["season"], round=params["round"], api_json = self.run_request(season=params["season"], round_no=params["round"],
criteria=filters["criteria"], resource=filters["resource"], value=filters["value"], criteria=filters["criteria"], resource=filters["resource"],
limit=params["paging"]["limit"], offset=params["paging"]["offset"]) value=filters["value"], limit=params["paging"]["limit"],
offset=params["paging"]["offset"])
return json["MRData"]["RaceTable"]["Races"] return api_json["MRData"]["RaceTable"]["Races"]

View File

@ -1,26 +1,30 @@
""" TypeConstructor class """
from ergast_py.constants.expected import Expected
from ergast_py.constants.status_type import StatusType
from ergast_py.helpers import Helpers
from ergast_py.models.average_speed import AverageSpeed from ergast_py.models.average_speed import AverageSpeed
from ergast_py.models.circuit import Circuit
from ergast_py.models.constructor import Constructor
from ergast_py.models.constructor_standing import ConstructorStanding from ergast_py.models.constructor_standing import ConstructorStanding
from ergast_py.models.driver import Driver from ergast_py.models.driver import Driver
from ergast_py.models.driver_standing import DriverStanding from ergast_py.models.driver_standing import DriverStanding
from ergast_py.models.fastest_lap import FastestLap from ergast_py.models.fastest_lap import FastestLap
from ergast_py.models.lap import Lap from ergast_py.models.lap import Lap
from ergast_py.models.location import Location from ergast_py.models.location import Location
from ergast_py.models.circuit import Circuit
from ergast_py.models.constructor import Constructor
from ergast_py.models.pit_stop import PitStop from ergast_py.models.pit_stop import PitStop
from ergast_py.models.race import Race from ergast_py.models.race import Race
from ergast_py.models.result import Result from ergast_py.models.result import Result
from ergast_py.helpers import Helpers
from ergast_py.constants.status_type import StatusType
from ergast_py.models.season import Season from ergast_py.models.season import Season
from ergast_py.models.standings_list import StandingsList from ergast_py.models.standings_list import StandingsList
from ergast_py.models.status import Status from ergast_py.models.status import Status
from ergast_py.models.timing import Timing from ergast_py.models.timing import Timing
from ergast_py.constants.expected import Expected
#pylint: disable=too-many-public-methods
class TypeConstructor(): class TypeConstructor():
""" """
Class for constructing types out of dicts Class for constructing types out of dicts
""" """
def __init__(self) -> None: def __init__(self) -> None:
@ -96,6 +100,9 @@ class TypeConstructor():
# #
def construct_location(self, location: dict) -> Location: def construct_location(self, location: dict) -> Location:
"""
Construct a Location from a JSON dictionary
"""
location = self._populate_missing_location(location=location) location = self._populate_missing_location(location=location)
return Location( return Location(
latitude=float(location["lat"]), latitude=float(location["lat"]),
@ -105,101 +112,137 @@ class TypeConstructor():
) )
def construct_circuit(self, circuit: dict) -> Circuit: def construct_circuit(self, circuit: dict) -> Circuit:
"""
Construct a Circuit from a JSON dictionary
"""
circuit = self._populate_missing_circuit(circuit) circuit = self._populate_missing_circuit(circuit)
return Circuit( return Circuit(
circuitId=circuit["circuitId"], circuit_id=circuit["circuitId"],
url=circuit["url"], url=circuit["url"],
circuitName=circuit["circuitName"], circuit_name=circuit["circuitName"],
location=self.construct_location(circuit["Location"]) location=self.construct_location(circuit["Location"])
) )
def construct_circuits(self, circuits: dict) -> list[Circuit]: def construct_circuits(self, circuits: dict) -> list[Circuit]:
"""
Construct a list of Circuits from a JSON dictionary
"""
return [self.construct_circuit(circuit) for circuit in circuits] return [self.construct_circuit(circuit) for circuit in circuits]
def construct_constructor(self, constructor: dict) -> Constructor: def construct_constructor(self, constructor: dict) -> Constructor:
"""
Construct a Constructor from a JSON dictionary
"""
constructor = self._populate_missing_constructor(constructor) constructor = self._populate_missing_constructor(constructor)
return Constructor( return Constructor(
constructorId=constructor["constructorId"], constructor_id=constructor["constructorId"],
url=constructor["url"], url=constructor["url"],
name=constructor["name"], name=constructor["name"],
nationality=constructor["nationality"] nationality=constructor["nationality"]
) )
def construct_constructors(self, constructors: dict) -> list[Constructor]: def construct_constructors(self, constructors: dict) -> list[Constructor]:
"""
Construct a list of Constructors from a JSON dictionary
"""
return [self.construct_constructor(constructor) for constructor in constructors] return [self.construct_constructor(constructor) for constructor in constructors]
def construct_driver(self, driver: dict) -> Driver: def construct_driver(self, driver: dict) -> Driver:
"""
Construct a Driver from a JSON dictionary
"""
driver = self._populate_missing_driver(driver) driver = self._populate_missing_driver(driver)
return Driver( return Driver(
driverId=driver["driverId"], driver_id=driver["driverId"],
permanentNumber=int(driver["permanentNumber"]), permanent_number=int(driver["permanentNumber"]),
code=driver["code"], code=driver["code"],
url=driver["url"], url=driver["url"],
givenName=driver["givenName"], given_name=driver["givenName"],
familyName=driver["familyName"], family_name=driver["familyName"],
dateOfBirth=Helpers().construct_date(driver["dateOfBirth"]), date_of_birth=Helpers().construct_date(driver["dateOfBirth"]),
nationality=driver["nationality"] nationality=driver["nationality"]
) )
def construct_drivers(self, drivers: dict) -> list[Driver]: def construct_drivers(self, drivers: dict) -> list[Driver]:
"""
Construct a list of Drivers from a JSON dictionary
"""
return [self.construct_driver(driver) for driver in drivers] return [self.construct_driver(driver) for driver in drivers]
def construct_race(self, race: dict) -> Race: def construct_race(self, race: dict) -> Race:
"""
Construct a Race from a JSON dictionary
"""
race = self._populate_missing_race(race) race = self._populate_missing_race(race)
return Race( return Race(
season=int(race["season"]), season=int(race["season"]),
round=int(race["round"]), round_no=int(race["round"]),
url=race["url"], url=race["url"],
raceName=race["raceName"], race_name=race["raceName"],
circuit=self.construct_circuit(race["Circuit"]), circuit=self.construct_circuit(race["Circuit"]),
date=Helpers().construct_datetime_str(date=race["date"], time=race["time"]), date=Helpers().construct_datetime_str(date=race["date"], time=race["time"]),
results=self.construct_results(race["Results"]), results=self.construct_results(race["Results"]),
firstPractice=Helpers().construct_datetime_dict(race["FirstPractice"]), first_practice=Helpers().construct_datetime_dict(race["FirstPractice"]),
secondPractice=Helpers().construct_datetime_dict(race["SecondPractice"]), second_practice=Helpers().construct_datetime_dict(race["SecondPractice"]),
thirdPractice=Helpers().construct_datetime_dict(race["ThirdPractice"]), third_practice=Helpers().construct_datetime_dict(race["ThirdPractice"]),
sprint=Helpers().construct_datetime_dict(race["Sprint"]), sprint=Helpers().construct_datetime_dict(race["Sprint"]),
sprintResults=self.construct_results(race["SprintResults"]), sprint_results=self.construct_results(race["SprintResults"]),
qualifying=Helpers().construct_datetime_dict(race["Qualifying"]), qualifying=Helpers().construct_datetime_dict(race["Qualifying"]),
qualifyingResults=self.construct_results(race["QualifyingResults"]), qualifying_results=self.construct_results(race["QualifyingResults"]),
pitStops=self.construct_pit_stops(race["PitStops"]), pit_stops=self.construct_pit_stops(race["PitStops"]),
laps=self.construct_laps(race["Laps"]) laps=self.construct_laps(race["Laps"])
) )
def construct_races(self, races: dict) -> list[Race]: def construct_races(self, races: dict) -> list[Race]:
"""
Construct a list of Races from a JSON dictionary
"""
return [self.construct_race(race) for race in races] return [self.construct_race(race) for race in races]
def construct_result(self, result: dict) -> Result: def construct_result(self, result: dict) -> Result:
"""
Construct a Result from a JSON dictionary
"""
result = self._populate_missing_result(result) result = self._populate_missing_result(result)
return Result( return Result(
number=int(result["number"]), number=int(result["number"]),
position=int(result["position"]), position=int(result["position"]),
positionText=result["positionText"], position_text=result["positionText"],
points=float(result["points"]), points=float(result["points"]),
driver=self.construct_driver(result["Driver"]), driver=self.construct_driver(result["Driver"]),
constructor=self.construct_constructor(result["Constructor"]), constructor=self.construct_constructor(result["Constructor"]),
grid=int(result["grid"]), grid=int(result["grid"]),
laps=int(result["laps"]), laps=int(result["laps"]),
status=int(StatusType().status_map[result["status"]]), status=int(StatusType().string_to_id[result["status"]]),
time=Helpers().construct_lap_time_millis(millis=result["Time"]), time=Helpers().construct_lap_time_millis(millis=result["Time"]),
fastestLap=self.construct_fastest_lap(result["FastestLap"]), fastest_lap=self.construct_fastest_lap(result["FastestLap"]),
q1=Helpers().format_lap_time(time=result["Q1"]), qual_1=Helpers().format_lap_time(time=result["Q1"]),
q2=Helpers().format_lap_time(time=result["Q2"]), qual_2=Helpers().format_lap_time(time=result["Q2"]),
q3=Helpers().format_lap_time(time=result["Q3"]), qual_3=Helpers().format_lap_time(time=result["Q3"]),
) )
def construct_results(self, results: dict) -> list[Result]: def construct_results(self, results: dict) -> list[Result]:
"""
Construct a list of Results from a JSON dictionary
"""
return [self.construct_result(result) for result in results] return [self.construct_result(result) for result in results]
def construct_fastest_lap(self, fastest_lap: dict) -> FastestLap: def construct_fastest_lap(self, fastest_lap: dict) -> FastestLap:
"""
Construct a FastestLap from a JSON dictionary
"""
fastest_lap = self._populate_missing_fastest_lap(fastest_lap) fastest_lap = self._populate_missing_fastest_lap(fastest_lap)
return FastestLap( return FastestLap(
rank=int(fastest_lap["rank"]), rank=int(fastest_lap["rank"]),
lap=int(fastest_lap["lap"]), lap=int(fastest_lap["lap"]),
time=Helpers().construct_lap_time(time=fastest_lap["Time"]), time=Helpers().construct_lap_time(time=fastest_lap["Time"]),
averageSpeed=self.construct_average_speed(fastest_lap["AverageSpeed"]) average_speed=self.construct_average_speed(fastest_lap["AverageSpeed"])
) )
def construct_average_speed(self, average_speed: dict) -> AverageSpeed: def construct_average_speed(self, average_speed: dict) -> AverageSpeed:
"""
Construct an AverageSpeed from a JSON dictionary
"""
average_speed = self._populate_missing_average_speed(average_speed) average_speed = self._populate_missing_average_speed(average_speed)
return AverageSpeed( return AverageSpeed(
units=average_speed["units"], units=average_speed["units"],
@ -207,19 +250,28 @@ class TypeConstructor():
) )
def construct_pit_stop(self, pit_stop: dict) -> PitStop: def construct_pit_stop(self, pit_stop: dict) -> PitStop:
"""
Construct a PitStop from a JSON dictionary
"""
pit_stop = self._populate_missing_pit_stop(pit_stop) pit_stop = self._populate_missing_pit_stop(pit_stop)
return PitStop( return PitStop(
driverId=pit_stop["driverId"], driver_id=pit_stop["driverId"],
lap=int(pit_stop["lap"]), lap=int(pit_stop["lap"]),
stop=int(pit_stop["stop"]), stop=int(pit_stop["stop"]),
localTime=Helpers().construct_local_time(pit_stop["time"]), local_time=Helpers().construct_local_time(pit_stop["time"]),
duration=Helpers().construct_pitstop_duration(pit_stop["duration"]) duration=Helpers().construct_pitstop_duration(pit_stop["duration"])
) )
def construct_pit_stops(self, pit_stops: dict) -> list[PitStop]: def construct_pit_stops(self, pit_stops: dict) -> list[PitStop]:
"""
Construct a list of PitStops from a JSON dictionary
"""
return [self.construct_pit_stop(pit_stop) for pit_stop in pit_stops] return [self.construct_pit_stop(pit_stop) for pit_stop in pit_stops]
def construct_lap(self, lap: dict) -> Lap: def construct_lap(self, lap: dict) -> Lap:
"""
Construct a Lap from a JSON dictionary
"""
lap = self._populate_missing_lap(lap) lap = self._populate_missing_lap(lap)
return Lap( return Lap(
number=int(lap["number"]), number=int(lap["number"]),
@ -227,20 +279,32 @@ class TypeConstructor():
) )
def construct_laps(self, laps: dict) -> list[Lap]: def construct_laps(self, laps: dict) -> list[Lap]:
"""
Construct a list of Laps from a JSON dictionary
"""
return [self.construct_lap(lap) for lap in laps] return [self.construct_lap(lap) for lap in laps]
def construct_timing(self, timing: dict) -> Timing: def construct_timing(self, timing: dict) -> Timing:
"""
Construct a Timing from a JSON dictionary
"""
timing = self._populate_missing_timing(timing) timing = self._populate_missing_timing(timing)
return Timing( return Timing(
driverId=timing["driverId"], driver_id=timing["driverId"],
position=int(timing["position"]), position=int(timing["position"]),
time=Helpers().format_lap_time(time=timing["time"]) time=Helpers().format_lap_time(time=timing["time"])
) )
def construct_timings(self, timings: dict) -> list[Timing]: def construct_timings(self, timings: dict) -> list[Timing]:
"""
Construct a list of Timings from a JSON dictionary
"""
return [self.construct_timing(timing) for timing in timings] return [self.construct_timing(timing) for timing in timings]
def construct_season(self, season: dict) -> Season: def construct_season(self, season: dict) -> Season:
"""
Construct a Season from a JSON dictionary
"""
season = self._populate_missing_season(season) season = self._populate_missing_season(season)
return Season( return Season(
season=int(season["season"]), season=int(season["season"]),
@ -248,24 +312,36 @@ class TypeConstructor():
) )
def construct_seasons(self, seasons: dict) -> list[Season]: def construct_seasons(self, seasons: dict) -> list[Season]:
"""
Construct a list of Seasons from a JSON dictionary
"""
return [self.construct_season(season) for season in seasons] return [self.construct_season(season) for season in seasons]
def construct_status(self, status: dict) -> Status: def construct_status(self, status: dict) -> Status:
"""
Construct a Status from a JSON dictionary
"""
status = self._populate_missing_status(status) status = self._populate_missing_status(status)
return Status( return Status(
statusId=int(status["statusId"]), status_id=int(status["statusId"]),
count=int(status["count"]), count=int(status["count"]),
status=status["status"] status=status["status"]
) )
def construct_statuses(self, statuses: dict) -> list[Season]: def construct_statuses(self, statuses: dict) -> list[Status]:
"""
Construct a list of Statuses from a JSON dictionary
"""
return [self.construct_status(status) for status in statuses] return [self.construct_status(status) for status in statuses]
def construct_driver_standing(self, standing: dict) -> DriverStanding: def construct_driver_standing(self, standing: dict) -> DriverStanding:
"""
Construct a DriverStanding from a JSON dictionary
"""
standing = self._populate_missing_driver_standing(standing) standing = self._populate_missing_driver_standing(standing)
return DriverStanding( return DriverStanding(
position=int(standing["position"]), position=int(standing["position"]),
positionText=standing["positionText"], position_text=standing["positionText"],
points=float(standing["points"]), points=float(standing["points"]),
wins=int(standing["wins"]), wins=int(standing["wins"]),
driver=self.construct_driver(standing["Driver"]), driver=self.construct_driver(standing["Driver"]),
@ -273,29 +349,45 @@ class TypeConstructor():
) )
def construct_driver_standings(self, standings: dict) -> list[DriverStanding]: def construct_driver_standings(self, standings: dict) -> list[DriverStanding]:
"""
Construct a list of DriverStandings from a JSON dictionary
"""
return [self.construct_driver_standing(standing) for standing in standings] return [self.construct_driver_standing(standing) for standing in standings]
def construct_constructor_standing(self, standing: dict) -> ConstructorStanding: def construct_constructor_standing(self, standing: dict) -> ConstructorStanding:
"""
Construct a ConstructorStanding from a JSON dictionary
"""
standing = self._populate_missing_constructor_standing(standing) standing = self._populate_missing_constructor_standing(standing)
return ConstructorStanding( return ConstructorStanding(
position=int(standing["position"]), position=int(standing["position"]),
positionText=standing["positionText"], position_text=standing["positionText"],
points=float(standing["points"]), points=float(standing["points"]),
wins=int(standing["wins"]), wins=int(standing["wins"]),
constructor=self.construct_constructor(standing["Constructor"]) constructor=self.construct_constructor(standing["Constructor"])
) )
def construct_constructor_standings(self, standings: dict) -> list[ConstructorStanding]: def construct_constructor_standings(self, standings: dict) -> list[ConstructorStanding]:
"""
Construct a list of ConstructorStandings from a JSON dictionary
"""
return [self.construct_constructor_standing(standing) for standing in standings] return [self.construct_constructor_standing(standing) for standing in standings]
def construct_standings_list(self, standings_list: dict) -> StandingsList: def construct_standings_list(self, standings_list: dict) -> StandingsList:
"""
Construct a StandingsList from a JSON dictionary
"""
standings_list = self._populate_missing_standings_list(standings_list) standings_list = self._populate_missing_standings_list(standings_list)
return StandingsList( return StandingsList(
season=int(standings_list["season"]), season=int(standings_list["season"]),
round=int(standings_list["round"]), round_no=int(standings_list["round"]),
driverStandings=self.construct_driver_standings(standings_list["DriverStandings"]), driver_standings=self.construct_driver_standings(standings_list["DriverStandings"]),
constructorStandings=self.construct_constructor_standings(standings_list["ConstructorStandings"]) constructor_standings=self.construct_constructor_standings(
standings_list["ConstructorStandings"])
) )
def construct_standings_lists(self, standings_lists: dict) -> list[StandingsList]: def construct_standings_lists(self, standings_lists: dict) -> list[StandingsList]:
"""
Construct a list of StandingsLists from a JSON dictionary
"""
return [self.construct_standings_list(standings_list) for standings_list in standings_lists] return [self.construct_standings_list(standings_list) for standings_list in standings_lists]