diff --git a/.pylintrc b/.pylintrc new file mode 100644 index 0000000..be4c787 --- /dev/null +++ b/.pylintrc @@ -0,0 +1,5 @@ +[MASTER] + +disable=too-many-instance-attributes, + too-many-arguments, + too-many-locals \ No newline at end of file diff --git a/README.md b/README.md index eb3404c..f51bdcd 100644 --- a/README.md +++ b/README.md @@ -146,7 +146,7 @@ More detail on the available functions within the ``Ergast()`` class is availabl RETURN functions
-> 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 | | ------------------------- | --------------------- | diff --git a/ergast_py/constants/expected.py b/ergast_py/constants/expected.py index 6331635..b27337c 100644 --- a/ergast_py/constants/expected.py +++ b/ergast_py/constants/expected.py @@ -1,139 +1,229 @@ +""" Expected class """ + class Expected(): """ - Storage of the expected keys returned and their types - """ + Representations of the types expected to be found within a model. - location = { - "lat": "float", - "long": "float", - "locality": "string", - "country": "string", - } + Each model has a set of keys, and the types expected. - circuit = { - "circuitId": "string", - "url": "string", - "circuitName": "string", - "Location": "string", - } + Types are stored as one of the following strings: + * "int" + * "float" + * "string" + * "dict" +""" - constructor = { - "constructorId": "string", - "url": "string", - "name": "string", - "nationality": "string", - } + @property + def location(self): + """ + Return the expected types of a Location + """ + return { + "lat": "float", + "long": "float", + "locality": "string", + "country": "string", + } - driver = { - "driverId": "string", - "permanentNumber": "int", - "code": "string", - "url": "string", - "givenName": "string", - "familyName": "string", - "dateOfBirth": "string", - "nationality": "string", - } + @property + def circuit(self): + """ + Return the expected types of a Circuit + """ + return { + "circuitId": "string", + "url": "string", + "circuitName": "string", + "Location": "string", + } - race = { - "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", - } + @property + def constructor(self): + """ + Return the expected types of a Constructor + """ + return { + "constructorId": "string", + "url": "string", + "name": "string", + "nationality": "string", + } - result = { - "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", - } - - fastest_lap = { - "rank": "int", - "lap": "int", - "Time": "dict", - "AverageSpeed": "dict", - } + @property + def driver(self): + """ + Return the expected types of a Driver + """ + return { + "driverId": "string", + "permanentNumber": "int", + "code": "string", + "url": "string", + "givenName": "string", + "familyName": "string", + "dateOfBirth": "string", + "nationality": "string", + } - average_speed = { - "units": "string", - "speed": "float", - } + @property + def race(self): + """ + Return the expected types of a Race + """ + 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", + } - pit_stop = { - "driverId": "string", - "lap": "int", - "stop": "int", - "time": "string", - "duration": "string", - } + @property + def result(self): + """ + 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", + } - lap = { - "number": "int", - "Timings": "dict", - } + @property + def fastest_lap(self): + """ + Return the expected types of a Fastest Lap + """ + return { + "rank": "int", + "lap": "int", + "Time": "dict", + "AverageSpeed": "dict", + } - timing = { - "driverId": "string", - "position": "int", - "time": "string", - } + @property + def average_speed(self): + """ + Return the expected types of a Average Speed + """ + return { + "units": "string", + "speed": "float", + } - season = { - "season": "int", - "url": "string", - } + @property + def pit_stop(self): + """ + Return the expected types of a Pit Stop + """ + return { + "driverId": "string", + "lap": "int", + "stop": "int", + "time": "string", + "duration": "string", + } - status = { - "statusId": "int", - "count": "int", - "status": "string" - } + @property + def lap(self): + """ + Return the expected types of a Lap + """ + return { + "number": "int", + "Timings": "dict", + } - driver_standing = { - "position": "int", - "positionText": "string", - "points": "float", - "wins": "int", - "Driver": "dict", - "Constructors": "dict" - } + @property + def timing(self): + """ + Return the expected types of a Timing + """ + return { + "driverId": "string", + "position": "int", + "time": "string", + } - constructor_standing = { - "position": "int", - "positionText": "string", - "points": "float", - "wins": "int", - "Constructor": "dict" - } + @property + def season(self): + """ + Return the expected types of a Season + """ + return { + "season": "int", + "url": "string", + } - standings_list = { - "season": "int", - "round": "int", - "DriverStandings": "dict", - "ConstructorStandings": "dict" - } \ No newline at end of file + @property + def status(self): + """ + Return the expected types of a Status + """ + return { + "statusId": "int", + "count": "int", + "status": "string" + } + + @property + def driver_standing(self): + """ + Return the expected types of a Driver Standing + """ + 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" + } diff --git a/ergast_py/constants/status_type.py b/ergast_py/constants/status_type.py index e8153ab..13c00d4 100644 --- a/ergast_py/constants/status_type.py +++ b/ergast_py/constants/status_type.py @@ -1,142 +1,294 @@ +""" StatusType class """ + class StatusType(): """ - A mapping of String onto the Status ID for that type + Mappings between ID and Strings for StatusType """ - status_map = { - "": 0, - "Finished": 1, - "Disqualified": 2, - "Accident": 3, - "Collision": 4, - "Engine": 5, - "Gearbox": 6, - "Transmission": 7, - "Clutch": 8, - "Hydraulics": 9, - "Electrical": 10, - "+1 Lap": 11, - "+2 Laps": 12, - "+3 Laps": 13, - "+4 Laps": 14, - "+5 Laps": 15, - "+6 Laps": 16, - "+7 Laps": 17, - "+8 Laps": 18, - "+9 Laps": 19, - "Spun off": 20, - "Radiator": 21, - "Suspension": 22, - "Brakes": 23, - "Differential": 24, - "Overheating": 25, - "Mechanical": 26, - "Tyre": 27, - "Driver Seat": 28, - "Puncture": 29, - "Driveshaft": 30, - "Retired": 31, - "Fuel pressure": 32, - "Front wing": 33, - "Water pressure": 34, - "Refuelling": 35, - "Wheel": 36, - "Throttle": 37, - "Steering": 38, - "Technical": 39, - "Electronics": 40, - "Broken wing": 41, - "Heat shield fire": 42, - "Exhaust": 43, - "Oil leak": 44, - "+11 Laps": 45, - "Wheel rim": 46, - "Water leak": 47, - "Fuel pump": 48, - "Track rod": 49, - "+17 Laps": 50, - "Oil pressure": 51, - "+13 Laps": 53, - "Withdrew": 54, - "+12 Laps": 55, - "Engine fire": 56, - "+26 Laps": 58, - "Tyre puncture": 59, - "Out of fuel": 60, - "Wheel nut": 61, - "Not classified": 62, - "Pneumatics": 63, - "Handling": 64, - "Rear wing": 65, - "Fire": 66, - "Wheel bearing": 67, - "Physical": 68, - "Fuel system": 69, - "Oil line": 70, - "Fuel rig": 71, - "Launch control": 72, - "Injured": 73, - "Fuel": 74, - "Power loss": 75, - "Vibrations": 76, - "107% Rule": 77, - "Safety": 78, - "Drivetrain": 79, - "Ignition": 80, - "Did not qualify": 81, - "Injury": 82, - "Chassis": 83, - "Battery": 84, - "Stalled": 85, - "Halfshaft": 86, - "Crankshaft": 87, - "+10 Laps": 88, - "Safety concerns": 89, - "Not restarted": 90, - "Alternator": 91, - "Underweight": 92, - "Safety belt": 93, - "Oil pump": 94, - "Fuel leak": 95, - "Excluded": 96, - "Did not prequalify": 97, - "Injection": 98, - "Distributor": 99, - "Driver unwell": 100, - "Turbo": 101, - "CV joint": 102, - "Water pump": 103, - "Fatal accident": 104, - "Spark plugs": 105, - "Fuel pipe": 106, - "Eye injury": 107, - "Oil pipe": 108, - "Axle": 109, - "Water pipe": 110, - "+14 Laps": 111, - "+15 Laps": 112, - "+25 Laps": 113, - "+18 Laps": 114, - "+22 Laps": 115, - "+16 Laps": 116, - "+24 Laps": 117, - "+29 Laps": 118, - "+23 Laps": 119, - "+21 Laps": 120, - "Magneto": 121, - "+44 Laps": 122, - "+30 Laps": 123, - "+19 Laps": 124, - "+46 Laps": 125, - "Supercharger": 126, - "+20 Laps": 127, - "+42 Laps": 128, - "Engine misfire": 129, - "Collision damage": 130, - "Power Unit": 131, - "ERS": 132, - "Brake duct": 135, - "Seat": 136, - "Damage": 137, - "Debris": 138, - "Illness": 139, - } \ No newline at end of file + + @property + def string_to_id(self): + """ + Return the map of StatusType strings to ids + """ + return { + "": 0, + "Finished": 1, + "Disqualified": 2, + "Accident": 3, + "Collision": 4, + "Engine": 5, + "Gearbox": 6, + "Transmission": 7, + "Clutch": 8, + "Hydraulics": 9, + "Electrical": 10, + "+1 Lap": 11, + "+2 Laps": 12, + "+3 Laps": 13, + "+4 Laps": 14, + "+5 Laps": 15, + "+6 Laps": 16, + "+7 Laps": 17, + "+8 Laps": 18, + "+9 Laps": 19, + "Spun off": 20, + "Radiator": 21, + "Suspension": 22, + "Brakes": 23, + "Differential": 24, + "Overheating": 25, + "Mechanical": 26, + "Tyre": 27, + "Driver Seat": 28, + "Puncture": 29, + "Driveshaft": 30, + "Retired": 31, + "Fuel pressure": 32, + "Front wing": 33, + "Water pressure": 34, + "Refuelling": 35, + "Wheel": 36, + "Throttle": 37, + "Steering": 38, + "Technical": 39, + "Electronics": 40, + "Broken wing": 41, + "Heat shield fire": 42, + "Exhaust": 43, + "Oil leak": 44, + "+11 Laps": 45, + "Wheel rim": 46, + "Water leak": 47, + "Fuel pump": 48, + "Track rod": 49, + "+17 Laps": 50, + "Oil pressure": 51, + "+13 Laps": 53, + "Withdrew": 54, + "+12 Laps": 55, + "Engine fire": 56, + "+26 Laps": 58, + "Tyre puncture": 59, + "Out of fuel": 60, + "Wheel nut": 61, + "Not classified": 62, + "Pneumatics": 63, + "Handling": 64, + "Rear wing": 65, + "Fire": 66, + "Wheel bearing": 67, + "Physical": 68, + "Fuel system": 69, + "Oil line": 70, + "Fuel rig": 71, + "Launch control": 72, + "Injured": 73, + "Fuel": 74, + "Power loss": 75, + "Vibrations": 76, + "107% Rule": 77, + "Safety": 78, + "Drivetrain": 79, + "Ignition": 80, + "Did not qualify": 81, + "Injury": 82, + "Chassis": 83, + "Battery": 84, + "Stalled": 85, + "Halfshaft": 86, + "Crankshaft": 87, + "+10 Laps": 88, + "Safety concerns": 89, + "Not restarted": 90, + "Alternator": 91, + "Underweight": 92, + "Safety belt": 93, + "Oil pump": 94, + "Fuel leak": 95, + "Excluded": 96, + "Did not prequalify": 97, + "Injection": 98, + "Distributor": 99, + "Driver unwell": 100, + "Turbo": 101, + "CV joint": 102, + "Water pump": 103, + "Fatal accident": 104, + "Spark plugs": 105, + "Fuel pipe": 106, + "Eye injury": 107, + "Oil pipe": 108, + "Axle": 109, + "Water pipe": 110, + "+14 Laps": 111, + "+15 Laps": 112, + "+25 Laps": 113, + "+18 Laps": 114, + "+22 Laps": 115, + "+16 Laps": 116, + "+24 Laps": 117, + "+29 Laps": 118, + "+23 Laps": 119, + "+21 Laps": 120, + "Magneto": 121, + "+44 Laps": 122, + "+30 Laps": 123, + "+19 Laps": 124, + "+46 Laps": 125, + "Supercharger": 126, + "+20 Laps": 127, + "+42 Laps": 128, + "Engine misfire": 129, + "Collision damage": 130, + "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", + } diff --git a/ergast_py/ergast.py b/ergast_py/ergast.py index db313e3..b12f455 100644 --- a/ergast_py/ergast.py +++ b/ergast_py/ergast.py @@ -1,3 +1,5 @@ +""" Ergast class """ + from __future__ import annotations from typing import Callable @@ -14,9 +16,21 @@ from ergast_py.requester import Requester from ergast_py.type_constructor import TypeConstructor +#pylint: disable=too-many-public-methods 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: @@ -26,6 +40,11 @@ class Ergast(): def reset(self) -> None: + """ + Reset the Ergast query building. + + Should be called after a query is run to prevent forward interraction. + """ self.params = { "season": None, "seasons": None, @@ -52,74 +71,167 @@ class Ergast(): # def season(self, year: int="current") -> Ergast: + """ + Add a season to the current query + + >>> e.season(2022).get_races() + """ self.params["season"] = year return self 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 return self 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 return self def driver_str(self, driver: str) -> Ergast: + """ + Add a driver to the current query + + >>> e.driver_str("alonso").get_driver() + """ self.params["driver"] = driver return self 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 return self def constructor_str(self, constructor: str) -> Ergast: + """ + Add a constructor to the current query + + >>> e.constructor_str("mercedes").get_constructor() + """ self.params["constructor"] = constructor return self 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 return self 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 return self 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 return self 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 return self 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 return self 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 return self def circuit_str(self, circuit: str) -> Ergast: + """ + Add a circuit to the current query + + >>> e.circuit_str("silverstone").get_circuit() + """ self.params["circuit"] = circuit return self def status(self, status: int) -> Ergast: + """ + Add a finishing status to the current query + + >>> e.driver_str("alonso").status(2) + """ self.params["status"] = status return self 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 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 return self 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 return self 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 return self @@ -128,10 +240,20 @@ class 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 return self 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 return self @@ -156,191 +278,187 @@ class Ergast(): # Race and Results Queries 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: - 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]: - constructors_json = self.requester.get_constructors(self.params) - constructors = self.type_constructor.construct_constructors(constructors_json) - self.reset() - return constructors + """ + Get a list of constructors from the current query + """ + return self._get_items(self.requester.get_constructors, + self.type_constructor.construct_constructors) def get_constructor(self) -> Constructor: - constructors_json = self.requester.get_constructors(self.params) - constructors = self.type_constructor.construct_constructors(constructors_json) - self.reset() - if len(constructors) == 1: - return constructors[0] - else: - raise Exception("More than 1 item found") + """ + Get a constructor from the current query + """ + return self._get_item(self.requester.get_constructors, + self.type_constructor.construct_constructors) def get_drivers(self) -> list[Driver]: - drivers_json = self.requester.get_drivers(self.params) - drivers = self.type_constructor.construct_drivers(drivers_json) - self.reset() - return drivers + """ + Get a list of drivers from the current query + """ + return self._get_items(self.requester.get_drivers, + self.type_constructor.construct_drivers) def get_driver(self) -> Driver: - drivers_json = self.requester.get_drivers(self.params) - drivers = self.type_constructor.construct_drivers(drivers_json) - self.reset() - if len(drivers) == 1: - return drivers[0] - else: - raise Exception("More than 1 item found") + """ + Get a driver from the current query + """ + return self._get_item(self.requester.get_drivers, + self.type_constructor.construct_drivers) def get_qualifyings(self) -> list[Race]: - qualify_json = self.requester.get_qualifying(self.params) - qualifying = self.type_constructor.construct_races(qualify_json) - self.reset() - return qualifying + """ + Get a list of qualifyings from the current query + """ + return self._get_items(self.requester.get_qualifying, + self.type_constructor.construct_races) def get_qualifying(self) -> Race: - qualify_json = self.requester.get_qualifying(self.params) - qualifying = self.type_constructor.construct_races(qualify_json) - self.reset() - if len(qualifying) == 1: - return qualifying[0] - else: - raise Exception("More than 1 item found") + """ + Get a qualifying from the current query + """ + return self._get_item(self.requester.get_qualifying, + self.type_constructor.construct_races) def get_sprints(self) -> list[Race]: - sprint_json = self.requester.get_sprints(self.params) - sprint = self.type_constructor.construct_races(sprint_json) - self.reset() - return sprint + """ + Get a list of sprints from the current query + """ + return self._get_items(self.requester.get_sprints, + self.type_constructor.construct_races) def get_sprint(self) -> Race: - sprint_json = self.requester.get_sprints(self.params) - sprint = self.type_constructor.construct_races(sprint_json) - self.reset() - if len(sprint) == 1: - return sprint[0] - else: - raise Exception("More than 1 item found") + """ + Get a sprint from the current query + """ + return self._get_item(self.requester.get_sprints, + self.type_constructor.construct_races) def get_results(self) -> list[Race]: - results_json = self.requester.get_results(self.params) - results = self.type_constructor.construct_races(results_json) - self.reset() - return results + """ + Get a list of results from the current query + """ + return self._get_items(self.requester.get_results, + self.type_constructor.construct_races) def get_result(self) -> Race: - results_json = self.requester.get_results(self.params) - results = self.type_constructor.construct_races(results_json) - self.reset() - if len(results) == 1: - return results[0] - else: - raise Exception("More than 1 item found") + """ + Get a result from the current query + """ + return self._get_item(self.requester.get_results, + self.type_constructor.construct_races) def get_races(self) -> list[Race]: - races_json = self.requester.get_races(self.params) - races = self.type_constructor.construct_races(races_json) - self.reset() - return races + """ + Get a list of races from the current query + """ + return self._get_items(self.requester.get_races, + self.type_constructor.construct_races) def get_race(self) -> Race: - races_json = self.requester.get_races(self.params) - races = self.type_constructor.construct_races(races_json) - self.reset() - if len(races) == 1: - return races[0] - else: - raise Exception("More than 1 item found") + """ + Get a race from the current query + """ + return self._get_item(self.requester.get_races, + self.type_constructor.construct_races) def get_seasons(self) -> list[Season]: - seasons_json = self.requester.get_seasons(self.params) - seasons = self.type_constructor.construct_seasons(seasons_json) - self.reset() - return seasons + """ + Get a list of seasons from the current query + """ + return self._get_items(self.requester.get_seasons, + self.type_constructor.construct_seasons) def get_season(self) -> Season: - seasons_json = self.requester.get_seasons(self.params) - seasons = self.type_constructor.construct_seasons(seasons_json) - self.reset() - if len(seasons) == 1: - return seasons[0] - else: - raise Exception("More than 1 item found") + """ + Get a season from the current query + """ + return self._get_item(self.requester.get_seasons, + self.type_constructor.construct_seasons) def get_statuses(self) -> list[Status]: - statuses_json = self.requester.get_statuses(self.params) - statuses = self.type_constructor.construct_statuses(statuses_json) - self.reset() - return statuses + """ + Get a list of statuses from the current query + """ + return self._get_items(self.requester.get_statuses, + self.type_constructor.construct_statuses) def get_status(self) -> Status: - statuses_json = self.requester.get_statuses(self.params) - statuses = self.type_constructor.construct_statuses(statuses_json) - self.reset() - if len(statuses) == 1: - return statuses[0] - else: - raise Exception("More than 1 item found") + """ + Get a status from the current query + """ + return self._get_item(self.requester.get_statuses, + self.type_constructor.construct_statuses) # Standings Queries 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) - self.reset() - return standings_lists + """ + Get a list of driver standings from the current query + """ + return self._get_items(self.requester.get_driver_standings, + self.type_constructor.construct_driver_standings) 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) - self.reset() - if len(standings_lists) == 1: - return standings_lists[0] - else: - raise Exception("More than 1 item found") + """ + Get a driver standing from the current query + """ + return self._get_item(self.requester.get_driver_standings, + self.type_constructor.construct_driver_standings) 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) - self.reset() - return standings_lists + """ + Get a list of constructor standings from the current query + """ + return self._get_items(self.requester.get_constructor_standings, + self.type_constructor.construct_constructor_standings) 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) - self.reset() - if len(standings_lists) == 1: - return standings_lists[0] - else: - raise Exception("More than 1 item found") + """ + Get a constructor standing from the current query + """ + return self._get_item(self.requester.get_constructor_standings, + self.type_constructor.construct_constructor_standings) # Laps and Pit Stops Queries def get_laps(self) -> list[Race]: - laps_json = self.requester.get_laps(self.params) - laps = self.type_constructor.construct_races(laps_json) - self.reset() - return laps + """ + Get a list of laps from the current query + """ + return self._get_items(self.requester.get_laps, + self.type_constructor.construct_races) def get_lap(self) -> Race: - laps_json = self.requester.get_laps(self.params) - laps = self.type_constructor.construct_races(laps_json) - self.reset() - if len(laps) == 1: - return laps[0] - else: - raise Exception("More than 1 item found") + """ + Get a lap from the current query + """ + return self._get_item(self.requester.get_laps, + self.type_constructor.construct_races) 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) - self.reset() - return pit_stops + """ + Get a list of pit stops from the current query + """ + return self._get_items(self.requester.get_pit_stops, + self.type_constructor.construct_races) 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) - self.reset() - if len(pit_stops) == 1: - return pit_stops[0] - else: - raise Exception("More than 1 item found") + """ + Get a pit stop from the current query + """ + return self._get_item(self.requester.get_pit_stops, + self.type_constructor.construct_races) diff --git a/ergast_py/helpers.py b/ergast_py/helpers.py index 9bfee38..15cde7d 100644 --- a/ergast_py/helpers.py +++ b/ergast_py/helpers.py @@ -1,44 +1,84 @@ +""" Helpers class """ + import datetime class Helpers: + """ + Helpers for the construction of models + """ + 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 = new_datetime.replace(tzinfo=datetime.timezone.utc) return new_datetime - def construct_datetime_dict(self, dict: dict) -> datetime.datetime: - if "date" not in dict or "time" not in dict: + def construct_datetime_dict(self, datetime_dict: dict) -> datetime.datetime: + """ + 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 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: + """ + Construct a datetime.date from a date string + """ elements = date.split("-") 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: + """ + Construct a datetime.time (lap time) from a dict containing the millis + """ if "millis" in millis: value = int(millis["millis"]) return datetime.datetime.fromtimestamp(value/1000.0).time() return None def format_lap_time(self, time: str) -> datetime.time: + """ + Construct a datetime.time (lap time) from a time string + """ if time != "": return datetime.datetime.strptime(time, "%M:%S.%f").time() return None 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: value = time["time"] return self.format_lap_time(value) return None 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 None 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 None diff --git a/ergast_py/models/average_speed.py b/ergast_py/models/average_speed.py index e21be93..f5f461d 100644 --- a/ergast_py/models/average_speed.py +++ b/ergast_py/models/average_speed.py @@ -1,9 +1,15 @@ +""" AverageSpeed class """ + from dataclasses import dataclass +from ergast_py.models.model import Model + + @dataclass -class AverageSpeed: +class AverageSpeed(Model): """ Representation of a Drivers Average Speed + Average Speeds may contain: units: String speed: Float @@ -12,12 +18,3 @@ class AverageSpeed: def __init__(self, units: str, speed: float) -> None: self.units = units 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})" \ No newline at end of file diff --git a/ergast_py/models/circuit.py b/ergast_py/models/circuit.py index cdafc68..03cd9ae 100644 --- a/ergast_py/models/circuit.py +++ b/ergast_py/models/circuit.py @@ -1,28 +1,25 @@ +""" Circuit class """ + from dataclasses import dataclass + from ergast_py.models.location import Location +from ergast_py.models.model import Model + @dataclass -class Circuit: +class Circuit(Model): """ Representation of a Formula One Circuit + Circuits may contain: - circuitId: String + circuit_id: String url: String - circuitName: String + circuit_name: String location: Location """ - def __init__(self, circuitId: str, url: str, circuitName: str, location: Location) -> None: - self.circuitId = circuitId + def __init__(self, circuit_id: str, url: str, circuit_name: str, location: Location) -> None: + self.circuit_id = circuit_id self.url = url - self.circuitName = circuitName + self.circuit_name = circuit_name 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})" \ No newline at end of file diff --git a/ergast_py/models/constructor.py b/ergast_py/models/constructor.py index b997ed8..a9ecb63 100644 --- a/ergast_py/models/constructor.py +++ b/ergast_py/models/constructor.py @@ -1,27 +1,24 @@ +""" Constructor class """ + from dataclasses import dataclass +from ergast_py.models.model import Model + + @dataclass -class Constructor: +class Constructor(Model): """ Representation of a Formula One Team + Constructors may contain: - constructorId: String + constructor_id: String url: String name: String nationality: String """ - def __init__(self, constructorId: str, url: str, name: str, nationality: str) -> None: - self.constructorId = constructorId + def __init__(self, constructor_id: str, url: str, name: str, nationality: str) -> None: + self.constructor_id = constructor_id self.url = url self.name = name 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})" \ No newline at end of file diff --git a/ergast_py/models/constructor_standing.py b/ergast_py/models/constructor_standing.py index 49b288a..516ceca 100644 --- a/ergast_py/models/constructor_standing.py +++ b/ergast_py/models/constructor_standing.py @@ -1,31 +1,28 @@ +""" ConstructorStanding class """ + from dataclasses import dataclass from ergast_py.models.constructor import Constructor +from ergast_py.models.model import Model + @dataclass -class ConstructorStanding: +class ConstructorStanding(Model): """ Representation of a Formula One Constructor's standing in a Season + Constructor Standings may contain: position: Integer - positionText: String + position_text: String points: Float wins: Integer 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.positionText = positionText + self.position_text = position_text self.points = points self.wins = wins 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})" \ No newline at end of file diff --git a/ergast_py/models/driver.py b/ergast_py/models/driver.py index bf265a1..265e065 100644 --- a/ergast_py/models/driver.py +++ b/ergast_py/models/driver.py @@ -1,38 +1,34 @@ -from dataclasses import dataclass -from ergast_py.helpers import Helpers +""" Driver class """ + import datetime +from dataclasses import dataclass + +from ergast_py.models.model import Model + @dataclass -class Driver: +class Driver(Model): """ Representation of a Formula One driver + Drivers may contain: - driverId: String - permanentNumber: Integer + driver_id: String + permanent_number: Integer code: String url: String - givenName: String - familyName: String - dateOfBirth: datetime.date + given_name: String + family_name: String + date_of_birth: datetime.date nationality: String """ - def __init__(self, driverId: str, code: str, url: str, givenName: str, familyName: str, dateOfBirth: datetime.date, - nationality: str, permanentNumber: int) -> None: - self.driverId = driverId - self.permanentNumber = permanentNumber + def __init__(self, driver_id: str, code: str, url: str, given_name: str, family_name: str, + date_of_birth: datetime.date, nationality: str, permanent_number: int) -> None: + self.driver_id = driver_id + self.permanent_number = permanent_number self.code = code self.url = url - self.givenName = givenName - self.familyName = familyName - self.dateOfBirth = dateOfBirth + self.given_name = given_name + self.family_name = family_name + self.date_of_birth = date_of_birth 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})" \ No newline at end of file diff --git a/ergast_py/models/driver_standing.py b/ergast_py/models/driver_standing.py index 747166f..07ab218 100644 --- a/ergast_py/models/driver_standing.py +++ b/ergast_py/models/driver_standing.py @@ -1,35 +1,31 @@ -from dataclasses import dataclass -from ergast_py.models.constructor import Constructor +""" DriverStanding class """ +from dataclasses import dataclass + +from ergast_py.models.constructor import Constructor from ergast_py.models.driver import Driver +from ergast_py.models.model import Model + @dataclass -class DriverStanding: +class DriverStanding(Model): """ Representation of a Formula One Driver's standing in a Season + Driver Standings may contain: position: Integer - positionText: String + position_text: String points: Float wins: Integer driver: Driver 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: self.position = position - self.positionText = positionText + self.position_text = position_text self.points = points self.wins = wins self.driver = driver 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})" \ No newline at end of file diff --git a/ergast_py/models/fastest_lap.py b/ergast_py/models/fastest_lap.py index 29bc08c..04cf207 100644 --- a/ergast_py/models/fastest_lap.py +++ b/ergast_py/models/fastest_lap.py @@ -1,29 +1,27 @@ -from dataclasses import dataclass -from ergast_py.models.average_speed import AverageSpeed +""" FastestLap class """ + import datetime +from dataclasses import dataclass + +from ergast_py.models.average_speed import AverageSpeed +from ergast_py.models.model import Model + @dataclass -class FastestLap: +class FastestLap(Model): """ Representation of a Fastest Lap for a Formula One Driver + Fastest Laps may contain: rank: Integer lap: Integer 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.lap = lap self.time = time - self.averageSpeed = averageSpeed - 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})" \ No newline at end of file + self.average_speed = average_speed diff --git a/ergast_py/models/lap.py b/ergast_py/models/lap.py index 248be80..fb5509f 100644 --- a/ergast_py/models/lap.py +++ b/ergast_py/models/lap.py @@ -1,11 +1,16 @@ +""" Lap class """ + from dataclasses import dataclass +from ergast_py.models.model import Model from ergast_py.models.timing import Timing + @dataclass -class Lap: +class Lap(Model): """ Representation of a single Lap from a Formula One race + Laps may contain: number: Integer timings: Timing[] @@ -14,12 +19,3 @@ class Lap: def __init__(self, number: int, timings: list[Timing]) -> None: self.number = number 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})" \ No newline at end of file diff --git a/ergast_py/models/location.py b/ergast_py/models/location.py index d5825e5..c2f9e11 100644 --- a/ergast_py/models/location.py +++ b/ergast_py/models/location.py @@ -1,9 +1,15 @@ +""" Location class """ + from dataclasses import dataclass +from ergast_py.models.model import Model + + @dataclass -class Location: +class Location(Model): """ Representation of a Location for a Formula One Circuit + Locations may contain: lat: Float long: Float @@ -16,12 +22,3 @@ class Location: self.longitude = longitude self.locality = locality 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})" \ No newline at end of file diff --git a/ergast_py/models/model.py b/ergast_py/models/model.py new file mode 100644 index 0000000..bb1ce19 --- /dev/null +++ b/ergast_py/models/model.py @@ -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})" diff --git a/ergast_py/models/pit_stop.py b/ergast_py/models/pit_stop.py index bddf890..acd3b31 100644 --- a/ergast_py/models/pit_stop.py +++ b/ergast_py/models/pit_stop.py @@ -1,31 +1,28 @@ -from dataclasses import dataclass +""" PitStop class """ + import datetime +from dataclasses import dataclass + +from ergast_py.models.model import Model + @dataclass -class PitStop: +class PitStop(Model): """ Representation of a single Pit Stop from a Formula One race + PitStops may contain: - driverId: String + driver_id: String lap: Integer stop: Integer - localTime: datetime.datetime + local_time: datetime.datetime 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: - self.driverId = driverId + self.driver_id = driver_id self.lap = lap self.stop = stop - self.localTime = localTime + self.local_time = local_time 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})" \ No newline at end of file diff --git a/ergast_py/models/race.py b/ergast_py/models/race.py index c70e197..1684173 100644 --- a/ergast_py/models/race.py +++ b/ergast_py/models/race.py @@ -1,62 +1,58 @@ -from dataclasses import dataclass -import datetime +""" Race class """ + +import datetime +from dataclasses import dataclass -from ergast_py.helpers import Helpers from ergast_py.models.circuit import Circuit 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.result import Result + @dataclass -class Race: +class Race(Model): """ Representation of a single Race from a Formula One season + Races may contain: season: Integer - round: Integer + round_no: Integer url: String - raceName: String + race_name: String circuit: Circuit date: datetime.datetime results: Result[] - firstPractice: datetime.datetime - secondPractice: datetime.datetime - thirdPractice: datetime.datetime + first_practice: datetime.datetime + second_practice: datetime.datetime + third_practice: datetime.datetime sprint: datetime.datetime - sprintResults: Result[] + sprint_results: Result[] qualifying: datetime.datetime - qualifyingResults: Result[] - pitStops: PitStop[] + qualifying_results: Result[] + pit_stops: PitStop[] laps: Lap[] """ - def __init__(self, season: int, round: int, url: str, raceName: str, circuit: Circuit, date: datetime.datetime, - results: list[Result], firstPractice: datetime.datetime, secondPractice: datetime.datetime, - thirdPractice: datetime.datetime, sprint: datetime.datetime, sprintResults: list[Result], - qualifying: datetime.datetime, qualifyingResults: list[Result], pitStops: list[PitStop], - laps: list[Lap]) -> None: + def __init__(self, season: int, round_no: int, url: str, race_name: str, circuit: Circuit, + date: datetime.datetime, results: list[Result], first_practice: datetime.datetime, + second_practice: datetime.datetime, third_practice: datetime.datetime, + sprint: datetime.datetime, sprint_results: list[Result], + qualifying: datetime.datetime, qualifying_results: list[Result], + pit_stops: list[PitStop], laps: list[Lap]) -> None: self.season = season - self.round = round + self.round_no = round_no self.url = url - self.raceName = raceName + self.race_name = race_name self.circuit = circuit self.date = date self.results = results - self.firstPractice = firstPractice - self.secondPractice = secondPractice - self.thirdPractice = thirdPractice + self.first_practice = first_practice + self.second_practice = second_practice + self.third_practice = third_practice self.sprint = sprint - self.sprintResults = sprintResults + self.sprint_results = sprint_results self.qualifying = qualifying - self.qualifyingResults = qualifyingResults - self.pitStops = pitStops + self.qualifying_results = qualifying_results + self.pit_stops = pit_stops 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})" diff --git a/ergast_py/models/result.py b/ergast_py/models/result.py index f89cb5e..ce832d1 100644 --- a/ergast_py/models/result.py +++ b/ergast_py/models/result.py @@ -1,18 +1,23 @@ -from dataclasses import dataclass -import datetime -from ergast_py.models.constructor import Constructor +""" Result class """ +import datetime +from dataclasses import dataclass + +from ergast_py.models.constructor import Constructor from ergast_py.models.driver import Driver from ergast_py.models.fastest_lap import FastestLap +from ergast_py.models.model import Model + @dataclass -class Result: +class Result(Model): """ Representation of a single Result from a Formula One race + Results may contain: number: Integer position: Integer - positionText: String + position_text: String points: Integer driver: Driver constructor: Constructor @@ -20,18 +25,19 @@ class Result: laps: Integer status: Integer time: datetime.time - fastestLap: FastestLap - q1: datetime.time - q2: datetime.time - q3: datetime.time + fastest_lap: FastestLap + qual_1: datetime.time + qual_2: datetime.time + qual_3: datetime.time """ - def __init__(self, number: int, position: int, positionText: str, points: float, driver: Driver, - constructor: Constructor, grid: int, laps: int, status: int, time: datetime.time, - fastestLap: FastestLap, q1: datetime.time, q2: datetime.time, q3: datetime.time) -> None: + def __init__(self, number: int, position: int, position_text: str, points: float, + driver: Driver, constructor: Constructor, grid: int, laps: int, status: int, + time: datetime.time, fastest_lap: FastestLap, qual_1: datetime.time, + qual_2: datetime.time, qual_3: datetime.time) -> None: self.number = number self.position = position - self.positionText = positionText + self.position_text = position_text self.points = points self.driver = driver self.constructor = constructor @@ -39,16 +45,7 @@ class Result: self.laps = laps self.status = status self.time = time - self.fastestLap = fastestLap - self.q1 = q1 - self.q2 = q2 - self.q3 = q3 - 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})" \ No newline at end of file + self.fastest_lap = fastest_lap + self.qual_1 = qual_1 + self.qual_2 = qual_2 + self.qual_3 = qual_3 diff --git a/ergast_py/models/season.py b/ergast_py/models/season.py index 20134ea..a734541 100644 --- a/ergast_py/models/season.py +++ b/ergast_py/models/season.py @@ -1,9 +1,15 @@ +""" Season class """ + from dataclasses import dataclass +from ergast_py.models.model import Model + + @dataclass -class Season: +class Season(Model): """ Representation of a single Season in Formula One + Seasons may contain: season: Integer url: String @@ -12,12 +18,3 @@ class Season: def __init__(self, season: int, url: str) -> None: self.season = season 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})" \ No newline at end of file diff --git a/ergast_py/models/standings_list.py b/ergast_py/models/standings_list.py index af154e4..5724b95 100644 --- a/ergast_py/models/standings_list.py +++ b/ergast_py/models/standings_list.py @@ -1,30 +1,27 @@ +""" StandingsList class """ + from dataclasses import dataclass -from ergast_py.models.driver_standing import DriverStanding + from ergast_py.models.constructor_standing import ConstructorStanding +from ergast_py.models.driver_standing import DriverStanding +from ergast_py.models.model import Model + @dataclass -class StandingsList: +class StandingsList(Model): """ Representation of a set of Standings from a time in Formula One + StandingsLists may contain: season: Integer - round: Integer - driverStandings: DriverStanding[] - constructorStandings: ConstructorStanding[] + round_no: Integer + driver_standings: DriverStanding[] + constructor_standings: ConstructorStanding[] """ - def __init__(self, season: int, round: int, driverStandings: list[DriverStanding], - constructorStandings: list[ConstructorStanding]) -> None: + def __init__(self, season: int, round_no: int, driver_standings: list[DriverStanding], + constructor_standings: list[ConstructorStanding]) -> None: self.season = season - self.round = round - self.driverStandings = driverStandings - self.constructorStandings = constructorStandings - 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})" \ No newline at end of file + self.round_no = round_no + self.driver_standings = driver_standings + self.constructor_standings = constructor_standings diff --git a/ergast_py/models/status.py b/ergast_py/models/status.py index 4148e34..ae9aa2b 100644 --- a/ergast_py/models/status.py +++ b/ergast_py/models/status.py @@ -1,25 +1,22 @@ +""" Status class """ + from dataclasses import dataclass +from ergast_py.models.model import Model + + @dataclass -class Status: +class Status(Model): """ Representation of the finishing status of a Driver in a Race + Statuses may contain: - statusId: Integer + status_id: Integer count: Integer status: String """ - def __init__(self, statusId: int, count: int, status: str) -> None: - self.statusId = statusId + def __init__(self, status_id: int, count: int, status: str) -> None: + self.status_id = status_id self.count = count 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})" \ No newline at end of file diff --git a/ergast_py/models/timing.py b/ergast_py/models/timing.py index 6aaae04..6e1b035 100644 --- a/ergast_py/models/timing.py +++ b/ergast_py/models/timing.py @@ -1,26 +1,22 @@ -from dataclasses import dataclass +""" Timing class """ + import datetime +from dataclasses import dataclass + +from ergast_py.models.model import Model + @dataclass -class Timing: +class Timing(Model): """ Representation of a single timing from a lap in Formula One Timings may contain: - driverId: String + driver_id: String position: Integer time: datetime.time """ - def __init__(self, driverId: str, position: int, time: datetime.time) -> None: - self.driverId = driverId + def __init__(self, driver_id: str, position: int, time: datetime.time) -> None: + self.driver_id = driver_id self.position = position 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})" \ No newline at end of file diff --git a/ergast_py/requester.py b/ergast_py/requester.py index f7b1da9..057b810 100644 --- a/ergast_py/requester.py +++ b/ergast_py/requester.py @@ -1,6 +1,8 @@ -import json -import requests +""" Requester class """ +import json + +import requests from uritemplate import URITemplate HOST = 'https://ergast.com/api' @@ -8,15 +10,10 @@ SERIES = 'f1' 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: - """ Acquire only the appropriate filters for Race/Results data """ return { "season": param["season"], "round": param["round"], @@ -40,10 +37,9 @@ class Requester(): } def _get_race_results_criteria(self, params: dict, resource: str) -> dict: - """ Split the data into criteria and resource for Race/Results """ criteria = [] 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(value) @@ -56,7 +52,6 @@ class Requester(): } def _get_standings_params(self, param: dict) -> dict: - """ Acquire only the appropriate filters for Standings data """ return { "season": param["season"], "round": param["round"], @@ -72,10 +67,9 @@ class Requester(): } def _get_standings_criteria(self, params: dict, resource: str) -> dict: - """ Split the data into criteria and resource for standings """ criteria = [] 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(value) @@ -88,7 +82,6 @@ class Requester(): } def _get_laps_pit_stops_params(self, param: dict) -> dict: - """ Acquire only the appropriate filters for Laps and Pit Stops data """ return { "season": param["season"], "round": param["round"], @@ -104,10 +97,9 @@ class Requester(): } 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 = [] 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(value) @@ -120,162 +112,216 @@ class Requester(): } - def run_request(self, season, round, criteria, resource, value=None, limit=None, offset=None) -> dict: - """ Takes values to run the request and return a dict """ + def run_request(self, season, round_no, criteria, resource, value=None, limit=None, + offset=None) -> dict: + """ + Takes values to run the request and return a dict + """ url_tmpl = URITemplate('https://ergast.com/api{/series}{/season}{/round}' '{/criteria*}{/resource}{/value}.json{?limit,offset}') - url = url_tmpl.expand(host=HOST, series=SERIES, - season=season, round=round, + url = url_tmpl.expand(host=HOST, series=SERIES, + season=season, round=round_no, criteria=criteria, resource=resource, value=value, limit=limit, offset=offset) response = requests.get(url) if response.status_code == 200: 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 # def get_circuits(self, param: dict) -> dict: + """ + Get the Circuits JSON from the Ergast API + """ params = self._get_race_results_params(param) filters = self._get_race_results_criteria(params, "circuits") - json = self.run_request(season=params["season"], round=params["round"], - criteria=filters["criteria"], resource=filters["resource"], value=filters["value"], - limit=params["paging"]["limit"], offset=params["paging"]["offset"]) + api_json = self.run_request(season=params["season"], round_no=params["round"], + criteria=filters["criteria"], resource=filters["resource"], + 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: + """ + Get the Constructors JSON from the Ergast API + """ params = self._get_race_results_params(param) filters = self._get_race_results_criteria(params, "constructors") - json = self.run_request(season=params["season"], round=params["round"], - criteria=filters["criteria"], resource=filters["resource"], value=filters["value"], - limit=params["paging"]["limit"], offset=params["paging"]["offset"]) + api_json = self.run_request(season=params["season"], round_no=params["round"], + criteria=filters["criteria"], resource=filters["resource"], + 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: + """ + Get the Drivers JSON from the Ergast API + """ params = self._get_race_results_params(param) filters = self._get_race_results_criteria(params, "drivers") - json = self.run_request(season=params["season"], round=params["round"], - criteria=filters["criteria"], resource=filters["resource"], value=filters["value"], - limit=params["paging"]["limit"], offset=params["paging"]["offset"]) + api_json = self.run_request(season=params["season"], round_no=params["round"], + criteria=filters["criteria"], resource=filters["resource"], + 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: + """ + Get the Qualifying JSON from the Ergast API + """ params = self._get_race_results_params(param) filters = self._get_race_results_criteria(params, "qualifying") - json = self.run_request(season=params["season"], round=params["round"], - criteria=filters["criteria"], resource=filters["resource"], value=filters["value"], - limit=params["paging"]["limit"], offset=params["paging"]["offset"]) + api_json = self.run_request(season=params["season"], round_no=params["round"], + criteria=filters["criteria"], resource=filters["resource"], + 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: + """ + Get the Sprints JSON from the Ergast API + """ params = self._get_race_results_params(param) filters = self._get_race_results_criteria(params, "sprint") - json = self.run_request(season=params["season"], round=params["round"], - criteria=filters["criteria"], resource=filters["resource"], value=filters["value"], - limit=params["paging"]["limit"], offset=params["paging"]["offset"]) + api_json = self.run_request(season=params["season"], round_no=params["round"], + criteria=filters["criteria"], resource=filters["resource"], + 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: + """ + Get the Results JSON from the Ergast API + """ params = self._get_race_results_params(param) filters = self._get_race_results_criteria(params, "results") - json = self.run_request(season=params["season"], round=params["round"], - criteria=filters["criteria"], resource=filters["resource"], value=filters["value"], - limit=params["paging"]["limit"], offset=params["paging"]["offset"]) + api_json = self.run_request(season=params["season"], round_no=params["round"], + criteria=filters["criteria"], resource=filters["resource"], + 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: + """ + Get the Races JSON from the Ergast API + """ params = self._get_race_results_params(param) filters = self._get_race_results_criteria(params, "races") - json = self.run_request(season=params["season"], round=params["round"], - criteria=filters["criteria"], resource=filters["resource"], value=filters["value"], - limit=params["paging"]["limit"], offset=params["paging"]["offset"]) + api_json = self.run_request(season=params["season"], round_no=params["round"], + criteria=filters["criteria"], resource=filters["resource"], + 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: + """ + Get the Seasons JSON from the Ergast API + """ params = self._get_race_results_params(param) filters = self._get_race_results_criteria(params, "seasons") - json = self.run_request(season=params["season"], round=params["round"], - criteria=filters["criteria"], resource=filters["resource"], value=filters["value"], - limit=params["paging"]["limit"], offset=params["paging"]["offset"]) + api_json = self.run_request(season=params["season"], round_no=params["round"], + criteria=filters["criteria"], resource=filters["resource"], + 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: + """ + Get the Statuses JSON from the Ergast API + """ params = self._get_race_results_params(param) filters = self._get_race_results_criteria(params, "status") - json = self.run_request(season=params["season"], round=params["round"], - criteria=filters["criteria"], resource=filters["resource"], value=filters["value"], - limit=params["paging"]["limit"], offset=params["paging"]["offset"]) + api_json = self.run_request(season=params["season"], round_no=params["round"], + criteria=filters["criteria"], resource=filters["resource"], + value=filters["value"], limit=params["paging"]["limit"], + offset=params["paging"]["offset"]) - return json["MRData"]["StatusTable"]["Status"] + return api_json["MRData"]["StatusTable"]["Status"] # # Standings # def get_driver_standings(self, param: dict) -> dict: + """ + Get the Driver Standings JSON from the Ergast API + """ params = self._get_standings_params(param) filters = self._get_standings_criteria(params, "driverStandings") - json = self.run_request(season=params["season"], round=params["round"], - criteria=filters["criteria"], resource=filters["resource"], value=filters["value"], - limit=params["paging"]["limit"], offset=params["paging"]["offset"]) + api_json = self.run_request(season=params["season"], round_no=params["round"], + criteria=filters["criteria"], resource=filters["resource"], + 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: + """ + Get the Constructor Standings JSON from the Ergast API + """ params = self._get_standings_params(param) filters = self._get_standings_criteria(params, "constructorStandings") - json = self.run_request(season=params["season"], round=params["round"], - criteria=filters["criteria"], resource=filters["resource"], value=filters["value"], - limit=params["paging"]["limit"], offset=params["paging"]["offset"]) + api_json = self.run_request(season=params["season"], round_no=params["round"], + criteria=filters["criteria"], resource=filters["resource"], + 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 # def get_laps(self, param: dict) -> dict: + """ + Get the Laps JSON from the Ergast API + """ params = self._get_laps_pit_stops_params(param) filters = self._get_laps_pit_stops_criteria(params, "laps") - json = self.run_request(season=params["season"], round=params["round"], - criteria=filters["criteria"], resource=filters["resource"], value=filters["value"], - limit=params["paging"]["limit"], offset=params["paging"]["offset"]) + api_json = self.run_request(season=params["season"], round_no=params["round"], + criteria=filters["criteria"], resource=filters["resource"], + 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: + """ + Get the Pit Stops JSON from the Ergast API + """ params = self._get_laps_pit_stops_params(param) filters = self._get_laps_pit_stops_criteria(params, "pitstops") - json = self.run_request(season=params["season"], round=params["round"], - criteria=filters["criteria"], resource=filters["resource"], value=filters["value"], - limit=params["paging"]["limit"], offset=params["paging"]["offset"]) + api_json = self.run_request(season=params["season"], round_no=params["round"], + criteria=filters["criteria"], resource=filters["resource"], + value=filters["value"], limit=params["paging"]["limit"], + offset=params["paging"]["offset"]) - return json["MRData"]["RaceTable"]["Races"] \ No newline at end of file + return api_json["MRData"]["RaceTable"]["Races"] diff --git a/ergast_py/type_constructor.py b/ergast_py/type_constructor.py index 6416c8b..65d1e14 100644 --- a/ergast_py/type_constructor.py +++ b/ergast_py/type_constructor.py @@ -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.circuit import Circuit +from ergast_py.models.constructor import Constructor from ergast_py.models.constructor_standing import ConstructorStanding from ergast_py.models.driver import Driver from ergast_py.models.driver_standing import DriverStanding from ergast_py.models.fastest_lap import FastestLap from ergast_py.models.lap import Lap 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.race import Race 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.standings_list import StandingsList from ergast_py.models.status import Status from ergast_py.models.timing import Timing -from ergast_py.constants.expected import Expected + +#pylint: disable=too-many-public-methods class TypeConstructor(): """ - Class for constructing types out of dicts + Class for constructing types out of dicts """ def __init__(self) -> None: @@ -96,6 +100,9 @@ class TypeConstructor(): # def construct_location(self, location: dict) -> Location: + """ + Construct a Location from a JSON dictionary + """ location = self._populate_missing_location(location=location) return Location( latitude=float(location["lat"]), @@ -105,101 +112,137 @@ class TypeConstructor(): ) def construct_circuit(self, circuit: dict) -> Circuit: + """ + Construct a Circuit from a JSON dictionary + """ circuit = self._populate_missing_circuit(circuit) return Circuit( - circuitId=circuit["circuitId"], + circuit_id=circuit["circuitId"], url=circuit["url"], - circuitName=circuit["circuitName"], + circuit_name=circuit["circuitName"], location=self.construct_location(circuit["Location"]) ) 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] def construct_constructor(self, constructor: dict) -> Constructor: + """ + Construct a Constructor from a JSON dictionary + """ constructor = self._populate_missing_constructor(constructor) return Constructor( - constructorId=constructor["constructorId"], + constructor_id=constructor["constructorId"], url=constructor["url"], name=constructor["name"], nationality=constructor["nationality"] ) 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] def construct_driver(self, driver: dict) -> Driver: + """ + Construct a Driver from a JSON dictionary + """ driver = self._populate_missing_driver(driver) return Driver( - driverId=driver["driverId"], - permanentNumber=int(driver["permanentNumber"]), + driver_id=driver["driverId"], + permanent_number=int(driver["permanentNumber"]), code=driver["code"], url=driver["url"], - givenName=driver["givenName"], - familyName=driver["familyName"], - dateOfBirth=Helpers().construct_date(driver["dateOfBirth"]), + given_name=driver["givenName"], + family_name=driver["familyName"], + date_of_birth=Helpers().construct_date(driver["dateOfBirth"]), nationality=driver["nationality"] ) 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] def construct_race(self, race: dict) -> Race: + """ + Construct a Race from a JSON dictionary + """ race = self._populate_missing_race(race) return Race( season=int(race["season"]), - round=int(race["round"]), + round_no=int(race["round"]), url=race["url"], - raceName=race["raceName"], + race_name=race["raceName"], circuit=self.construct_circuit(race["Circuit"]), date=Helpers().construct_datetime_str(date=race["date"], time=race["time"]), results=self.construct_results(race["Results"]), - firstPractice=Helpers().construct_datetime_dict(race["FirstPractice"]), - secondPractice=Helpers().construct_datetime_dict(race["SecondPractice"]), - thirdPractice=Helpers().construct_datetime_dict(race["ThirdPractice"]), + first_practice=Helpers().construct_datetime_dict(race["FirstPractice"]), + second_practice=Helpers().construct_datetime_dict(race["SecondPractice"]), + third_practice=Helpers().construct_datetime_dict(race["ThirdPractice"]), 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"]), - qualifyingResults=self.construct_results(race["QualifyingResults"]), - pitStops=self.construct_pit_stops(race["PitStops"]), + qualifying_results=self.construct_results(race["QualifyingResults"]), + pit_stops=self.construct_pit_stops(race["PitStops"]), laps=self.construct_laps(race["Laps"]) ) 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] def construct_result(self, result: dict) -> Result: + """ + Construct a Result from a JSON dictionary + """ result = self._populate_missing_result(result) return Result( number=int(result["number"]), position=int(result["position"]), - positionText=result["positionText"], + position_text=result["positionText"], points=float(result["points"]), driver=self.construct_driver(result["Driver"]), constructor=self.construct_constructor(result["Constructor"]), grid=int(result["grid"]), 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"]), - fastestLap=self.construct_fastest_lap(result["FastestLap"]), - q1=Helpers().format_lap_time(time=result["Q1"]), - q2=Helpers().format_lap_time(time=result["Q2"]), - q3=Helpers().format_lap_time(time=result["Q3"]), + fastest_lap=self.construct_fastest_lap(result["FastestLap"]), + qual_1=Helpers().format_lap_time(time=result["Q1"]), + qual_2=Helpers().format_lap_time(time=result["Q2"]), + qual_3=Helpers().format_lap_time(time=result["Q3"]), ) 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] 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) return FastestLap( rank=int(fastest_lap["rank"]), lap=int(fastest_lap["lap"]), 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: + """ + Construct an AverageSpeed from a JSON dictionary + """ average_speed = self._populate_missing_average_speed(average_speed) return AverageSpeed( units=average_speed["units"], @@ -207,40 +250,61 @@ class TypeConstructor(): ) 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) return PitStop( - driverId=pit_stop["driverId"], + driver_id=pit_stop["driverId"], lap=int(pit_stop["lap"]), 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"]) ) 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] def construct_lap(self, lap: dict) -> Lap: + """ + Construct a Lap from a JSON dictionary + """ lap = self._populate_missing_lap(lap) return Lap( number=int(lap["number"]), timings=self.construct_timings(lap["Timings"]) ) - + 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] def construct_timing(self, timing: dict) -> Timing: + """ + Construct a Timing from a JSON dictionary + """ timing = self._populate_missing_timing(timing) return Timing( - driverId=timing["driverId"], + driver_id=timing["driverId"], position=int(timing["position"]), time=Helpers().format_lap_time(time=timing["time"]) ) 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] def construct_season(self, season: dict) -> Season: + """ + Construct a Season from a JSON dictionary + """ season = self._populate_missing_season(season) return Season( season=int(season["season"]), @@ -248,24 +312,36 @@ class TypeConstructor(): ) 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] def construct_status(self, status: dict) -> Status: + """ + Construct a Status from a JSON dictionary + """ status = self._populate_missing_status(status) return Status( - statusId=int(status["statusId"]), + status_id=int(status["statusId"]), count=int(status["count"]), 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] def construct_driver_standing(self, standing: dict) -> DriverStanding: + """ + Construct a DriverStanding from a JSON dictionary + """ standing = self._populate_missing_driver_standing(standing) return DriverStanding( position=int(standing["position"]), - positionText=standing["positionText"], + position_text=standing["positionText"], points=float(standing["points"]), wins=int(standing["wins"]), driver=self.construct_driver(standing["Driver"]), @@ -273,29 +349,45 @@ class TypeConstructor(): ) 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] def construct_constructor_standing(self, standing: dict) -> ConstructorStanding: + """ + Construct a ConstructorStanding from a JSON dictionary + """ standing = self._populate_missing_constructor_standing(standing) return ConstructorStanding( position=int(standing["position"]), - positionText=standing["positionText"], + position_text=standing["positionText"], points=float(standing["points"]), wins=int(standing["wins"]), constructor=self.construct_constructor(standing["Constructor"]) ) 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] 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) return StandingsList( season=int(standings_list["season"]), - round=int(standings_list["round"]), - driverStandings=self.construct_driver_standings(standings_list["DriverStandings"]), - constructorStandings=self.construct_constructor_standings(standings_list["ConstructorStandings"]) + round_no=int(standings_list["round"]), + driver_standings=self.construct_driver_standings(standings_list["DriverStandings"]), + constructor_standings=self.construct_constructor_standings( + standings_list["ConstructorStandings"]) ) def construct_standings_lists(self, standings_lists: dict) -> list[StandingsList]: - return [self.construct_standings_list(standings_list) for standings_list in standings_lists] \ No newline at end of file + """ + Construct a list of StandingsLists from a JSON dictionary + """ + return [self.construct_standings_list(standings_list) for standings_list in standings_lists]