From 0b58321abf102b7b9d02b4b895ed2ee3cbdafbb8 Mon Sep 17 00:00:00 2001 From: HarryLudemann <60420781+HarryLudemann@users.noreply.github.com> Date: Mon, 16 Aug 2021 00:28:52 +1200 Subject: [PATCH] Convert from request to urllib, added get_routes --- README.md | 17 +++++++- metlink/metlink.py | 89 ++++++++++++++++++++++++++++++------------ requirements.txt | 2 +- setup.py | 4 +- tests/test_creation.py | 2 +- 5 files changed, 82 insertions(+), 32 deletions(-) diff --git a/README.md b/README.md index de3a447..01e3498 100644 --- a/README.md +++ b/README.md @@ -67,10 +67,11 @@ for pred in stop_predictions: ### Functions: | Function Name | Description | | ------------- |:-------------:| -| get_trip_updates | Trip Updates - Delays, cancellations, changed routes. Given nothing, returns list of dictionaries. | -| get_vehicle_positions | Vehicle Positions - API to get Information about vehicles including location. Given nothing, returns list of dictionaries. | +| get_trip_updates | Trip Updates - Delays, cancellations, changed routes. Given nothing, returns list of dictionaries. returns empty list if no trip delays or changes | +| get_vehicle_positions | Vehicle Positions - API to get Information about vehicles including location. Given nothing, returns list of dictionaries. if no busses are active returns empty list | | get_service_alerts | Trip Updates - Information about unforeseen events affecting routes, stops, or the network. Given nothing, returns list of dictionaries. | | get_stop_predictions | Passed stop_id, returns list of dictionary's | +| get_routes | Returns list of dictionarys of route infomation, optionally given stop_id as filter | #### Returned Dictionary Fields: @@ -110,3 +111,15 @@ for pred in stop_predictions: * arrival_time * trip_start_time * vehicle_id + +* **get_routes** + * id + * route_id + * agency_id + * route_short_name + * route_long_name + * route_desc + * route_type + * route_color + * route_text_color + * route_url diff --git a/metlink/metlink.py b/metlink/metlink.py index e82bbce..53dac75 100644 --- a/metlink/metlink.py +++ b/metlink/metlink.py @@ -1,33 +1,75 @@ -import requests - +import urllib3 +import json +import certifi class metlink(): - __version__ = '0.1' + __version__ = '0.0.3' base_url = 'https://api.opendata.metlink.org.nz/v1/' def __init__(self, API_KEY = None): self.API_KEY = API_KEY + if self.API_KEY is None: + raise ValueError('API_KEY not provided') + + + def get_metlink_data(self, API_Path): + """ Method passed API Path eg 'vehiclepositions' and returns response""" + http = urllib3.PoolManager( + cert_reqs='CERT_REQUIRED', + ca_certs=certifi.where() + ) + r = http.request( + 'GET', + API_Path, + headers={ + 'accept': 'application/json', + 'x-api-key': self.API_KEY + } + ) + if r.status == 200: + return json.loads(r.data.decode('utf-8')) + else: + raise ValueError('API Error:', json.loads(r.data.decode('utf-8'))) + + + # GTFS APIS Static public transport data for Wellington in GTFS (General Transit Feed Specification). + + def get_routes(self, stop_id = None): + """ Returns list of dictionarys of route infomation, optionally given stop_id as filter """ + if stop_id: + response = self.get_metlink_data('https://api.opendata.metlink.org.nz/v1/gtfs/routes?stop_id=' + str(stop_id)) + else: + response = self.get_metlink_data('https://api.opendata.metlink.org.nz/v1/gtfs/routes?stop_id=') + routes = [] + for entity in response: + route = { + 'id': entity['id'], + 'route_id': entity['route_id'], + 'agency_id': entity['agency_id'], + 'route_short_name': entity['route_short_name'], + 'route_long_name': entity['route_long_name'], + 'route_desc': entity['route_desc'], + 'route_type': entity['route_type'], + 'route_color': entity['route_color'], + 'route_text_color': entity['route_text_color'], + 'route_url': entity['route_url'], + } + routes.append(route) + return routes # GTFS-RT APIS - Real time data from the public transport network. - def get_rt_data(self, API_name): - """ Method passed API Name eg 'vehiclepositions' and returns response""" - headers = { - 'accept': 'application/json', - 'x-api-key': self.API_KEY - } - response = requests.get(self.base_url + 'gtfs-rt/' + API_name, headers=headers) - return response def get_vehicle_positions(self): """ Vehicle Positions - API to get Information about vehicles including location. Given nothing, returns list of dictionaries. + if no busses are active returns empty list """ - response = self.get_rt_data('vehiclepositions') + response = self.get_metlink_data('https://api.opendata.metlink.org.nz/v1/gtfs-rt/vehiclepositions') vehicle_positions = [] - for entity in response.json()['entity']: + for entity in response['entity']: vehicle_position = { 'vehicle_id': entity['vehicle']['vehicle']['id'], 'bearing': entity['vehicle']['position']['bearing'], @@ -41,10 +83,11 @@ def get_vehicle_positions(self): def get_trip_updates(self): """ Trip Updates - Delays, cancellations, changed routes. Given nothing, returns list of dictionaries. + if empty no trip delays or changes """ - response = self.get_rt_data('tripupdates') + response = self.get_metlink_data('https://api.opendata.metlink.org.nz/v1/gtfs-rt/tripupdates') trip_updates = [] - for entity in response.json()['entity']: + for entity in response['entity']: trip_update = { 'stop_id': entity['trip_update']['stop_time_update']['stop_id'], 'arrival_delay': entity['trip_update']['stop_time_update']['arrival']['delay'], @@ -60,9 +103,9 @@ def get_service_alerts(self): """ Trip Updates - Information about unforeseen events affecting routes, stops, or the network. Given nothing, returns list of dictionaries. """ - response = self.get_rt_data('servicealerts') + response = self.get_metlink_data('https://api.opendata.metlink.org.nz/v1/gtfs-rt/servicealerts') service_alerts = [] - for entity in response.json()['entity']: + for entity in response['entity']: service_alert = { 'active_period': entity['alert']['active_period'], 'effect': entity['alert']['effect'], @@ -77,21 +120,15 @@ def get_service_alerts(self): service_alerts.append(service_alert) return service_alerts - - # stop predicion API def get_stop_predictions(self, stop_id): """ Passed stop_id, returns list of dictionary's """ - headers = { - 'accept': 'application/json', - 'x-api-key': self.API_KEY - } - response = requests.get(self.base_url + 'stop-predictions?stop_id=' + str(stop_id), headers=headers) - + if not stop_id: raise ValueError('stop_id must be given') + response = self.get_metlink_data('https://api.opendata.metlink.org.nz/v1/stop-predictions?stop_id=' + str(stop_id)) stop_predictions = [] - for stop in response.json()['departures']: + for stop in response['departures']: prediction = { 'service_id': stop['service_id'], 'name': stop['name'], diff --git a/requirements.txt b/requirements.txt index 16d3b77..f24412b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,2 @@ pytest -requests \ No newline at end of file +urllib3 \ No newline at end of file diff --git a/setup.py b/setup.py index dfcc1b0..a8232f9 100644 --- a/setup.py +++ b/setup.py @@ -7,7 +7,7 @@ with codecs.open(os.path.join(here, "README.md"), encoding="utf-8") as fh: long_description = "\n" + fh.read() -VERSION = '0.0.2' +VERSION = '0.0.3' DESCRIPTION = 'API Wrapper for Metlink API' LONG_DESCRIPTION = 'A python package to easily access infomation from the official metlink api' @@ -20,7 +20,7 @@ description=DESCRIPTION, long_description_content_type="text/markdown", packages=find_packages(), - install_requires=['requests'], + install_requires=['urllib3'], keywords=['python', 'harryludemann', 'metlink', 'wellington', 'metlink-python'], classifiers=[ "Development Status :: 1 - Planning", diff --git a/tests/test_creation.py b/tests/test_creation.py index 65742cf..f44da9e 100644 --- a/tests/test_creation.py +++ b/tests/test_creation.py @@ -12,5 +12,5 @@ def test_creation(): """ Tests the main class object is instantiable """ - metlink_obj = metlink() + metlink_obj = metlink('abnaisfubas') assert metlink_obj \ No newline at end of file