PyTransportNSWv2 1.0.0__tar.gz → 1.0.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {PyTransportNSWv2-1.0.0 → PyTransportNSWv2-1.0.2}/PKG-INFO +1 -1
- {PyTransportNSWv2-1.0.0 → PyTransportNSWv2-1.0.2}/PyTransportNSWv2.egg-info/PKG-INFO +1 -1
- {PyTransportNSWv2-1.0.0 → PyTransportNSWv2-1.0.2}/TransportNSWv2/TransportNSWv2.py +29 -72
- {PyTransportNSWv2-1.0.0 → PyTransportNSWv2-1.0.2}/setup.py +1 -1
- {PyTransportNSWv2-1.0.0 → PyTransportNSWv2-1.0.2}/LICENSE +0 -0
- {PyTransportNSWv2-1.0.0 → PyTransportNSWv2-1.0.2}/PyTransportNSWv2.egg-info/SOURCES.txt +0 -0
- {PyTransportNSWv2-1.0.0 → PyTransportNSWv2-1.0.2}/PyTransportNSWv2.egg-info/TransportNSWv2.py +0 -0
- {PyTransportNSWv2-1.0.0 → PyTransportNSWv2-1.0.2}/PyTransportNSWv2.egg-info/dependency_links.txt +0 -0
- {PyTransportNSWv2-1.0.0 → PyTransportNSWv2-1.0.2}/PyTransportNSWv2.egg-info/requires.txt +0 -0
- {PyTransportNSWv2-1.0.0 → PyTransportNSWv2-1.0.2}/PyTransportNSWv2.egg-info/top_level.txt +0 -0
- {PyTransportNSWv2-1.0.0 → PyTransportNSWv2-1.0.2}/README.md +0 -0
- {PyTransportNSWv2-1.0.0 → PyTransportNSWv2-1.0.2}/TransportNSWv2/__init__.py +0 -0
- {PyTransportNSWv2-1.0.0 → PyTransportNSWv2-1.0.2}/setup.cfg +0 -0
@@ -35,7 +35,7 @@ ATTR_AVMS_TRIP_ID = 'avms_trip_id'
|
|
35
35
|
ATTR_REAL_TIME_TRIP_ID = 'real_time_trip_id'
|
36
36
|
ATTR_LATITUDE = 'latitude'
|
37
37
|
ATTR_LONGITUDE = 'longitude'
|
38
|
-
|
38
|
+
ATTR_GTFS_URI = 'gtfs_uri'
|
39
39
|
ATTR_ALERTS = 'alerts'
|
40
40
|
|
41
41
|
logger = logging.getLogger(__name__)
|
@@ -49,14 +49,6 @@ class TransportNSWv2(object):
|
|
49
49
|
|
50
50
|
def __init__(self):
|
51
51
|
"""Initialize the data object with default values."""
|
52
|
-
self.origin_id = None
|
53
|
-
self.destination_id = None
|
54
|
-
self.api_key = None
|
55
|
-
self.journey_wait_time = None
|
56
|
-
self.transport_type = None
|
57
|
-
self.strict_transport_type = None
|
58
|
-
self.raw_output = None
|
59
|
-
self.journeys_to_return = None
|
60
52
|
self.info = {
|
61
53
|
ATTR_DUE_IN : 'n/a',
|
62
54
|
ATTR_ORIGIN_STOP_ID : 'n/a',
|
@@ -79,7 +71,7 @@ class TransportNSWv2(object):
|
|
79
71
|
}
|
80
72
|
|
81
73
|
|
82
|
-
def check_stops(self, api_key, stops):
|
74
|
+
def check_stops(self, api_key, stops, home_assistant = False):
|
83
75
|
# Check the list of stops and return a JSON array of the stop details, plus if all the checked stops existed
|
84
76
|
# Return a JSON array of the results
|
85
77
|
|
@@ -121,22 +113,12 @@ class TransportNSWv2(object):
|
|
121
113
|
stop_detail = []
|
122
114
|
|
123
115
|
if response.status_code == 401:
|
124
|
-
# API key issue - log that, and don't bother with the other calls as they will all fail
|
125
|
-
#skip_api_calls = True
|
126
|
-
#all_stops_valid = False
|
127
|
-
#logger.error(f"Error {str(response.status_code)} calling /v1/tp/stop_finder API; invalid API key")
|
128
116
|
raise InvalidAPIKey("Invalid API key")
|
129
117
|
|
130
118
|
elif response.status_code == 403 or response.status_code == 429:
|
131
|
-
# We've exceeded the rate limit but that doesn't mean the stop isn't valid
|
132
|
-
# So raise an API rate limit exception and let the user decide how to handle it
|
133
|
-
#logger.warn(f"Error {str(response.status_code)} calling /v1/tp/stop_finder API; rate limit exceeded - assuming stop is valid")
|
134
119
|
raise APIRateLimitExceeded("API rate limit exceeded")
|
135
120
|
|
136
121
|
else:
|
137
|
-
# Raise a generic error exception
|
138
|
-
#all_stops_valid = False
|
139
|
-
#logger.error(f"Error {str(response.status_code)} calling /v1/tp/stop_finder API")
|
140
122
|
raise StopError("Unknown")
|
141
123
|
|
142
124
|
else:
|
@@ -145,25 +127,15 @@ class TransportNSWv2(object):
|
|
145
127
|
|
146
128
|
# Just a quick check - the presence of systemMessages signifies an error, otherwise we assume it's ok
|
147
129
|
if 'systemMessages' in stop_detail:
|
148
|
-
#all_stops_valid = False
|
149
|
-
#error_code = stop_detail['systemMessages'][0]['code']
|
150
130
|
error_text = stop_detail['systemMessages'][0]['text']
|
151
|
-
|
152
|
-
#logger.error(f"Error {error_code} calling /v1/tp/stop_finder API; {error_text} for Stop ID {stop}")
|
153
|
-
#raise StopError(f"Error {str(error_code)} ({str(error_text)}) calling stop finder API for stop ID {stop}")
|
154
|
-
raise StopError(f"{error_text}")
|
131
|
+
raise StopError(f"{error_text}", stop)
|
155
132
|
|
156
133
|
# Put in a pause here to try and make sure we stay under the 5 API calls/second limit
|
157
134
|
# Not usually an issue but if multiple processes are running multiple calls we might hit it
|
158
135
|
time.sleep(1.0)
|
159
136
|
|
160
137
|
except Exception as ex:
|
161
|
-
|
162
|
-
#error_code = 999
|
163
|
-
#stop_detail = []
|
164
|
-
|
165
|
-
#logger.error(f"Error {str(ex)} calling /v1/tp/stop_finder API; assuming stop is invalid")
|
166
|
-
raise StopError(f"Error '{ex}' calling stop finder API for stop ID {stop}")
|
138
|
+
raise StopError(f"Error '{ex}' calling stop finder API for stop ID {stop}", stop)
|
167
139
|
|
168
140
|
finally:
|
169
141
|
# Append the results to the JSON output - only return the 'isBest' location entry if there's more than one
|
@@ -172,7 +144,6 @@ class TransportNSWv2(object):
|
|
172
144
|
for location in stop_detail['locations']:
|
173
145
|
if location['isBest']:
|
174
146
|
stop_detail = location
|
175
|
-
|
176
147
|
break
|
177
148
|
|
178
149
|
else:
|
@@ -197,21 +168,10 @@ class TransportNSWv2(object):
|
|
197
168
|
"""Get the latest data from Transport NSW."""
|
198
169
|
fmt = '%Y-%m-%dT%H:%M:%SZ'
|
199
170
|
|
200
|
-
#self.name_origin = name_origin
|
201
|
-
#self.destination = name_destination
|
202
|
-
#self.api_key = api_key
|
203
|
-
#self.journey_wait_time = journey_wait_time
|
204
|
-
#self.transport_type = transport_type
|
205
|
-
#self.strict_transport_type = strict_transport_type
|
206
|
-
#self.raw_output = raw_output
|
207
|
-
#self.journeys_to_return = journeys_to_return
|
208
|
-
#self.route_filter = route_filter.lower()
|
209
|
-
#self.include_realtime_location = include_realtime_location
|
210
|
-
#self.include_alerts = include_alerts.lower()
|
211
|
-
#self.alert_type = alert_type.lower()
|
212
171
|
route_filter = route_filter.lower()
|
213
172
|
include_alerts = include_alerts.lower()
|
214
173
|
alert_type = alert_type.lower()
|
174
|
+
|
215
175
|
# This query always uses the current date and time - but add in any 'journey_wait_time' minutes
|
216
176
|
now_plus_wait = datetime.now() + timedelta(minutes = journey_wait_time)
|
217
177
|
itdDate = now_plus_wait.strftime('%Y%m%d')
|
@@ -233,7 +193,7 @@ class TransportNSWv2(object):
|
|
233
193
|
stop_error += stop['stop_id']+ ", "
|
234
194
|
|
235
195
|
#logger.error(f"Stop ID(s) {stop_error[:-2]} do not exist - exiting")
|
236
|
-
raise StopError (f"Stop ID(s) {stop_error[:-2]} do not exist")
|
196
|
+
raise StopError (f"Stop ID(s) {stop_error[:-2]} do not exist", stop_error)
|
237
197
|
#return None
|
238
198
|
|
239
199
|
# We don't control how many journeys are returned any more, so need to be careful of running out of valid journeys if there is a filter in place, particularly a strict filter
|
@@ -245,9 +205,8 @@ class TransportNSWv2(object):
|
|
245
205
|
'outputFormat=rapidJSON&coordOutputFormat=EPSG%3A4326' \
|
246
206
|
'&depArrMacro=dep&itdDate=' + itdDate + '&itdTime=' + itdTime + \
|
247
207
|
'&type_origin=any&name_origin=' + name_origin + \
|
248
|
-
'&type_destination=any&name_destination=' +
|
208
|
+
'&type_destination=any&name_destination=' + name_destination + \
|
249
209
|
'&TfNSWTR=true'
|
250
|
-
# '&calcNumberOfTrips=' + str(journeys_to_retrieve) + \
|
251
210
|
|
252
211
|
# Send the query and return an error if something goes wrong
|
253
212
|
# Otherwise store the response for the next steps
|
@@ -255,23 +214,19 @@ class TransportNSWv2(object):
|
|
255
214
|
response = requests.get(url, headers=header, timeout=10)
|
256
215
|
|
257
216
|
except Exception as ex:
|
258
|
-
|
259
|
-
#return None
|
260
|
-
raise TripError (f"Error '{str(ex)}' calling trip API for journey {self.name_origin} to {self.destination}")
|
217
|
+
raise TripError (f"Error '{str(ex)}' calling trip API for journey {name_origin} to {name_destination}")
|
261
218
|
|
262
219
|
# If we get bad status code, log error and return with n/a or an empty string
|
263
220
|
if response.status_code != 200:
|
264
221
|
if response.status_code == 401:
|
265
222
|
# API key issue
|
266
|
-
raise InvalidAPIKey("Error 'Invalid API key' calling trip API for journey {
|
223
|
+
raise InvalidAPIKey("Error 'Invalid API key' calling trip API for journey {name_origin} to {name_destination}")
|
267
224
|
|
268
225
|
elif response.status_code == 403 or response.status_code == 429:
|
269
|
-
raise APIRateLimitExceeded("Error 'API rate limit exceeded' calling trip API for journey {
|
270
|
-
#logger.error(f"Error {str(response.status_code)} calling /v1/tp/trip API; rate limit exceeded")
|
226
|
+
raise APIRateLimitExceeded("Error 'API rate limit exceeded' calling trip API for journey {name_origin} to {name_destination}")
|
271
227
|
|
272
228
|
else:
|
273
|
-
raise TripError(f"Error '{str(response.status_cude)}' calling trip API for journey {
|
274
|
-
#logger.error(f"Error {str(response.status_code)} calling /v1/tp/trip API; check API key")
|
229
|
+
raise TripError(f"Error '{str(response.status_cude)}' calling trip API for journey {name_origin} to {name_destination}")
|
275
230
|
|
276
231
|
return None
|
277
232
|
|
@@ -292,10 +247,7 @@ class TransportNSWv2(object):
|
|
292
247
|
retrieved_journeys = len(result['journeys'])
|
293
248
|
|
294
249
|
except:
|
295
|
-
|
296
|
-
#logger.error(f"Error {(str(err))} calling /v1/tp/trip API")
|
297
|
-
raise TripError(f"Error 'no journeys returned' calling trip API for journey {self.name_origin} to {self.destination}")
|
298
|
-
#return None
|
250
|
+
raise TripError(f"Error 'no journeys returned' calling trip API for journey {name_origin} to {name_destination}")
|
299
251
|
|
300
252
|
# Loop through the results applying filters where required, and generate the appropriate JSON output including an array of in-scope trips
|
301
253
|
json_output=''
|
@@ -371,15 +323,16 @@ class TransportNSWv2(object):
|
|
371
323
|
occupancy = first_stop['properties']['occupancy']
|
372
324
|
|
373
325
|
alerts = "[]"
|
374
|
-
if
|
326
|
+
if include_alerts != 'none':
|
375
327
|
# We'll be adding these to the returned JSON string as an array
|
376
328
|
# Only include alerts of the specified priority or greater, and of the specified type
|
377
|
-
alerts = self._find_alerts(legs,
|
329
|
+
alerts = self._find_alerts(legs, include_alerts, alert_type)
|
378
330
|
|
379
331
|
latitude = 'n/a'
|
380
332
|
longitude = 'n/a'
|
333
|
+
mode_url = 'n/a'
|
381
334
|
|
382
|
-
if
|
335
|
+
if include_realtime_location and realtimetripid != 'n/a':
|
383
336
|
# See if we can get the latitute and longitude via the Realtime Vehicle Positions API
|
384
337
|
# Build the URL(s) - some modes have multiple GTFS sources, unforunately
|
385
338
|
# Some travel modes require brute-forcing the API call a few times, so if we're sure of the URI,
|
@@ -449,12 +402,13 @@ class TransportNSWv2(object):
|
|
449
402
|
ATTR_CHANGES: changes,
|
450
403
|
ATTR_OCCUPANCY : occupancy,
|
451
404
|
ATTR_REAL_TIME_TRIP_ID : realtimetripid,
|
405
|
+
ATTR_GTFS_URI: mode_url,
|
452
406
|
ATTR_LATITUDE : latitude,
|
453
407
|
ATTR_LONGITUDE : longitude,
|
454
408
|
ATTR_ALERTS: json.loads(alerts)
|
455
409
|
}
|
456
410
|
|
457
|
-
if
|
411
|
+
if home_assistant:
|
458
412
|
self.info.update (
|
459
413
|
{ATTR_AVMS_TRIP_ID: avmstripid}
|
460
414
|
)
|
@@ -475,7 +429,7 @@ class TransportNSWv2(object):
|
|
475
429
|
|
476
430
|
current_journey_index = next_journey_index
|
477
431
|
|
478
|
-
json_output='{"journeys_to_return": ' + str(
|
432
|
+
json_output='{"journeys_to_return": ' + str(journeys_to_return) + ', "journeys_with_data": ' + str(found_journeys) + ', "journeys": [' + json_output + ']}'
|
479
433
|
return json_output
|
480
434
|
|
481
435
|
|
@@ -700,18 +654,21 @@ class TransportNSWv2(object):
|
|
700
654
|
return due
|
701
655
|
|
702
656
|
# Exceptions
|
703
|
-
class
|
704
|
-
""" Base error for all exceptions """
|
705
|
-
|
706
|
-
class InvalidAPIKey(TFNSWAPIError):
|
657
|
+
class InvalidAPIKey(Exception):
|
707
658
|
""" API key error """
|
708
659
|
|
709
|
-
class APIRateLimitExceeded(
|
660
|
+
class APIRateLimitExceeded(Exception):
|
710
661
|
""" API rate limit exceeded """
|
711
662
|
|
712
|
-
class StopError(
|
663
|
+
class StopError(Exception):
|
713
664
|
""" Stop-finder related error """
|
665
|
+
def __init__(self, message = "", stop_detail = ""):
|
666
|
+
super().__init__(message)
|
667
|
+
self.stop_detail = stop_detail
|
668
|
+
|
669
|
+
# def __str__(self):
|
670
|
+
# return f"{self.message}"
|
714
671
|
|
715
|
-
class TripError(
|
672
|
+
class TripError(Exception):
|
716
673
|
"""" Trip-finder related error """
|
717
674
|
|
@@ -5,7 +5,7 @@ with open("README.md", "r") as fh:
|
|
5
5
|
|
6
6
|
setuptools.setup(
|
7
7
|
name="PyTransportNSWv2",
|
8
|
-
version="1.0.
|
8
|
+
version="1.0.2",
|
9
9
|
author="andystewart999",
|
10
10
|
author_email="andy.stewart@live.com",
|
11
11
|
description="Get detailed per-trip transport information from TransportNSW",
|
File without changes
|
File without changes
|
{PyTransportNSWv2-1.0.0 → PyTransportNSWv2-1.0.2}/PyTransportNSWv2.egg-info/TransportNSWv2.py
RENAMED
File without changes
|
{PyTransportNSWv2-1.0.0 → PyTransportNSWv2-1.0.2}/PyTransportNSWv2.egg-info/dependency_links.txt
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|