From e495bffd223312bd5899b3993c8513351944bec7 Mon Sep 17 00:00:00 2001 From: Raphael Roberts Date: Tue, 18 Sep 2018 22:42:33 -0500 Subject: [PATCH 01/14] first files were wrong, new files are first step --- .gitignore | 3 +++ ctabus.py | 52 ++++++++++++++++++++++++++++++++++------------------ 2 files changed, 37 insertions(+), 18 deletions(-) diff --git a/.gitignore b/.gitignore index e2a5d37..4754fdb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ /cta_api_key.json __pycache__ *.pyc +*_out.json +*.pdf +*.bat \ No newline at end of file diff --git a/ctabus.py b/ctabus.py index dbd4d8d..bc60294 100644 --- a/ctabus.py +++ b/ctabus.py @@ -1,21 +1,37 @@ -from urllib import request +from urllib.parse import urlencode +from requests import get import json import datetime -import saveto -from timer import timer -bus_timer = timer(t='Bus times',e=True,o=False,a=True) -api = saveto.load('cta_api_key') +import argparse +test = False +test = True +api = "***REMOVED***" +def get_data(type,api_key = api,**args): + base_url = "http://www.ctabustracker.com/bustime/api/v2/{type}?{query}" + args['key'] = api_key + args['format'] = 'json' + url = base_url.format(type = type,query = urlencode(args)) + print(url) + input() + response = get(url) + data = json.loads(response.text) + return data['bustime-response'] + # print(url) +def print2d(values): + pass def get_times(stop_id,api_key = api): - url = "http://www.ctabustracker.com/bustime/api/v2/getpredictions?key={api_key}&stpid={stop_id}&format=json".format(stop_id = stop_id,api_key = api) - data = json.load(request.urlopen(url)) - times = list(map(lambda time: datetime.datetime.strptime(time['prdtm'],"%Y%m%d %H:%M"),data["bustime-response"]["prd"])) - return times -walk = datetime.timedelta(seconds = 60*4) -for i in range(6): - l = get_times(4752) - print(*map(lambda time: (str(time),str(time-walk)),l),sep = '\n',end = '\n\n') - try: - time = next(filter(bool,map(lambda time: time-walk if time-walk > datetime.datetime.today() else False,l))) - bus_timer(time) - except: - print("no times") + return get_data('getpredictions',api_key,stpid=stop_id) +def get_routes(api_key = api): + return get_data('getroutes',api_key) +def get_directions(route,api_key = api): + return get_data('getdirections',api_key,rt=route) +def get_stops(route,direction,api_key = api): + return get_data('getstops',api_key,rt = route,dir=direction) +if __name__ == "__main__": + if test: + data = get_times('4752') + else: + parser = argparse.ArgumentParser(prog = 'ctabus') + parser.add_argument('arg',metavar = 'stop-id | cross streets') + parser.add_argument('-r','--route') + parser.add_argument('-d','--direction') \ No newline at end of file From 6a35e23cbed023c4cd18cab826744b4dcc84f259 Mon Sep 17 00:00:00 2001 From: Raphael Roberts Date: Wed, 19 Sep 2018 12:32:58 -0500 Subject: [PATCH 02/14] Added paging print2d function --- .gitignore | 1 + ctabus.py | 7 +++++++ print2d.py | 40 ++++++++++++++++++++++++++++++++++++++++ requirements.txt | 2 ++ 4 files changed, 50 insertions(+) create mode 100644 print2d.py create mode 100644 requirements.txt diff --git a/.gitignore b/.gitignore index 4754fdb..4870e80 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ /cta_api_key.json +/output __pycache__ *.pyc *_out.json diff --git a/ctabus.py b/ctabus.py index bc60294..3fc0a19 100644 --- a/ctabus.py +++ b/ctabus.py @@ -3,9 +3,11 @@ from requests import get import json import datetime import argparse +from editdistance import eval as editdistance test = False test = True api = "***REMOVED***" + def get_data(type,api_key = api,**args): base_url = "http://www.ctabustracker.com/bustime/api/v2/{type}?{query}" args['key'] = api_key @@ -17,16 +19,21 @@ def get_data(type,api_key = api,**args): data = json.loads(response.text) return data['bustime-response'] # print(url) + def print2d(values): pass def get_times(stop_id,api_key = api): return get_data('getpredictions',api_key,stpid=stop_id) + def get_routes(api_key = api): return get_data('getroutes',api_key) + def get_directions(route,api_key = api): return get_data('getdirections',api_key,rt=route) + def get_stops(route,direction,api_key = api): return get_data('getstops',api_key,rt = route,dir=direction) + if __name__ == "__main__": if test: data = get_times('4752') diff --git a/print2d.py b/print2d.py new file mode 100644 index 0000000..076850b --- /dev/null +++ b/print2d.py @@ -0,0 +1,40 @@ +import datetime +from pydoc import pager +def str_coerce(s,**kwargs): + if isinstance(s,datetime.datetime): + return s.strftime(kwargs['datetime_format']) + else: + return str(s) +def print2d(l,datetime_format = "%A, %B %e, %Y %H:%M:%S",seperator= ' | ',spacer = ' ',bottom = '=',l_end = '|',r_end = '|',interactive = False): + l = [[str_coerce(s,datetime_format = datetime_format) for s in row] for row in l] + + max_col = [] + for row in l: + for i,col in enumerate(row): + try: + max_col[i] = max(max_col[i],len(col)) + except IndexError: + max_col.append(len(col)) + + if l_end and r_end: + fmt_row = f'{l_end} {{content}} {r_end}' + else: + fmt_row = '{content}' + + done = [] + for row in l: + content = seperator.join(col.ljust(max_col[i],spacer) for i,col in enumerate(row)) + done.append(fmt_row.format(content = content)) + + if bottom: + bottom = bottom*len(done[0]) + row_sep = ('\n'+bottom+'\n') + else: + row_sep = '\n' + final = row_sep.join(done) + if bottom: + final = '\n'.join((bottom,final,bottom)) + if interactive: + pager(final) + else: + return final \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..414733f --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +editdistance +requests \ No newline at end of file From f7af686063044e7ee06c43a0d0e802590b7c9ad6 Mon Sep 17 00:00:00 2001 From: Raphael Roberts Date: Wed, 19 Sep 2018 14:52:01 -0500 Subject: [PATCH 03/14] Search function and took out api key --- .gitignore | 2 +- ctabus.py | 15 +++------------ main.py | 10 ++++++++++ search.py | 22 ++++++++++++++++++++++ 4 files changed, 36 insertions(+), 13 deletions(-) create mode 100644 main.py create mode 100644 search.py diff --git a/.gitignore b/.gitignore index 4870e80..1a4bdfd 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ -/cta_api_key.json +/cta_api_key /output __pycache__ *.pyc diff --git a/ctabus.py b/ctabus.py index 3fc0a19..6727cac 100644 --- a/ctabus.py +++ b/ctabus.py @@ -2,11 +2,10 @@ from urllib.parse import urlencode from requests import get import json import datetime -import argparse -from editdistance import eval as editdistance test = False test = True -api = "***REMOVED***" +with open('cta_api_key') as file: + api = file.read() def get_data(type,api_key = api,**args): base_url = "http://www.ctabustracker.com/bustime/api/v2/{type}?{query}" @@ -33,12 +32,4 @@ def get_directions(route,api_key = api): def get_stops(route,direction,api_key = api): return get_data('getstops',api_key,rt = route,dir=direction) - -if __name__ == "__main__": - if test: - data = get_times('4752') - else: - parser = argparse.ArgumentParser(prog = 'ctabus') - parser.add_argument('arg',metavar = 'stop-id | cross streets') - parser.add_argument('-r','--route') - parser.add_argument('-d','--direction') \ No newline at end of file + diff --git a/main.py b/main.py new file mode 100644 index 0000000..4e23b19 --- /dev/null +++ b/main.py @@ -0,0 +1,10 @@ +from argparse import parser +parser = argparse.ArgumentParser(prog = 'ctabus') +parser.add_argument('arg',metavar = 'stop-id | cross streets') +parser.add_argument('-r','--route') +parser.add_argument('-d','--direction') +args = parser.parse_args() +if args.arg.isdecimal(): + pass +else: + pass \ No newline at end of file diff --git a/search.py b/search.py new file mode 100644 index 0000000..53d93fc --- /dev/null +++ b/search.py @@ -0,0 +1,22 @@ +from editdistance import eval as editdistance +import re +import json +class StopSearch: + def __init__(self,query): + parts = re.split(r' ?(?:and|&) ?',query) + self.query = ' & '.join(parts) + self.query_reversed = ' & '.join(reversed(parts)) + def __call__(self,stop): + stop = stop.lower() + return min( + editdistance(self.query,stop), + editdistance(self.query_reversed,stop) + ) + def __str__(self): + return '{}|{}'.format(self.query,self.query_reversed) + def __repr__(self): + return str(self) +if __name__ == "__main__": + with open('stops_out.json') as file: + data = json.load(file) + names = [stop['stpnm'] for stop in data['stops']] \ No newline at end of file From 6e1f3ca40edace57432cc124a6a1aaa0aaac016d Mon Sep 17 00:00:00 2001 From: Raphael Roberts Date: Thu, 20 Sep 2018 16:53:53 -0500 Subject: [PATCH 04/14] added gen_list, should make cmd printing easier, no fill for last row in print2d --- ctabus.py | 6 ----- main.py | 74 ++++++++++++++++++++++++++++++++++++++++++++++-------- print2d.py | 11 ++++---- search.py | 19 +++++++++++--- 4 files changed, 85 insertions(+), 25 deletions(-) diff --git a/ctabus.py b/ctabus.py index 6727cac..daca7a6 100644 --- a/ctabus.py +++ b/ctabus.py @@ -1,9 +1,6 @@ from urllib.parse import urlencode from requests import get import json -import datetime -test = False -test = True with open('cta_api_key') as file: api = file.read() @@ -17,10 +14,7 @@ def get_data(type,api_key = api,**args): response = get(url) data = json.loads(response.text) return data['bustime-response'] - # print(url) -def print2d(values): - pass def get_times(stop_id,api_key = api): return get_data('getpredictions',api_key,stpid=stop_id) diff --git a/main.py b/main.py index 4e23b19..9365c9e 100644 --- a/main.py +++ b/main.py @@ -1,10 +1,64 @@ -from argparse import parser -parser = argparse.ArgumentParser(prog = 'ctabus') -parser.add_argument('arg',metavar = 'stop-id | cross streets') -parser.add_argument('-r','--route') -parser.add_argument('-d','--direction') -args = parser.parse_args() -if args.arg.isdecimal(): - pass -else: - pass \ No newline at end of file +# from argparse import parser +from print2d import print2d +import re +# parser = argparse.ArgumentParser(prog = 'ctabus') +# parser.add_argument('arg',metavar = 'stop-id | cross streets') +# parser.add_argument('-r','--route',default = None) +# parser.add_argument('-d','--direction',default = None) +# args = parser.parse_args() +def numb_sort(str): + n = 40 + try: + return re.sub(r'\d+',lambda match: match.group(0).rjust(n,'0'),str) + except Exception as E: + print(str) + raise E + +def gen_list(objs,data,*displays,key = None,sort = 0,num_pic = True): + k = displays[sort] + display_data = {obj[k]:obj[data] for obj in objs} + srt_keys = sorted(display_data.keys(),key=key) + + display = sorted( + [ + [obj[d] for d in displays] for obj in objs + ], + key = lambda row: key(row[sort]) + ) + if num_pic: + display = [[i] + data for i,data in enumerate(display)] + + opts = { + 'spacer':' ', + 'seperator':' ', + 'interactive': True, + 'bottom':'=', + 'l_end':'<', + 'r_end':'>', + } + print2d(display,**opts) + if num_pic: + which = None + while not which: + try: + which = srt_keys[int(input('Which one?: '))] + except ValueError: + which = None + return display_data[which] + else: + ret = None + while not ret: + try: + ret = display_data[input('Which one?: ')] + except KeyError: + pass + return ret + + +if __name__ == "__main__": + import json + with open('stops_out.json') as file: + d= json.load(file) + + d = d['stops'] + print(gen_list(d,'stpid','stpnm',key=numb_sort,num_pic=True)) diff --git a/print2d.py b/print2d.py index 076850b..bf3326a 100644 --- a/print2d.py +++ b/print2d.py @@ -16,14 +16,15 @@ def print2d(l,datetime_format = "%A, %B %e, %Y %H:%M:%S",seperator= ' | ',spacer except IndexError: max_col.append(len(col)) - if l_end and r_end: - fmt_row = f'{l_end} {{content}} {r_end}' - else: - fmt_row = '{content}' + fmt_row = '{content}' + if l_end: + fmt_row = f'{l_end} ' + fmt_row + if r_end: + fmt_row = fmt_row + f' {r_end}' done = [] for row in l: - content = seperator.join(col.ljust(max_col[i],spacer) for i,col in enumerate(row)) + content = seperator.join(col.ljust(max_col[i],spacer if i < len(row)-1 or r_end else ' ') for i,col in enumerate(row)) done.append(fmt_row.format(content = content)) if bottom: diff --git a/search.py b/search.py index 53d93fc..f0dd163 100644 --- a/search.py +++ b/search.py @@ -3,14 +3,22 @@ import re import json class StopSearch: def __init__(self,query): - parts = re.split(r' ?(?:and|&) ?',query) + query = query.lower() + parts = re.split(r' ?(?:(?[^\)]+)\)',stop) + ret= [ editdistance(self.query,stop), - editdistance(self.query_reversed,stop) + editdistance(self.query_reversed,stop), + ] + if paren: + paren = paren.group('data') + ret.append(editdistance(self.query,paren)) + return min( + ret ) def __str__(self): return '{}|{}'.format(self.query,self.query_reversed) @@ -19,4 +27,7 @@ class StopSearch: if __name__ == "__main__": with open('stops_out.json') as file: data = json.load(file) - names = [stop['stpnm'] for stop in data['stops']] \ No newline at end of file + names = [stop['stpnm'] for stop in data['stops']] + while True: + q = StopSearch(input('Search: ')) + print('\n'.join(sorted(names,key=q))) \ No newline at end of file From b0b95a8fc72387ea34b71ec2006e1a146555c13a Mon Sep 17 00:00:00 2001 From: Raphael Roberts Date: Thu, 20 Sep 2018 19:06:01 -0500 Subject: [PATCH 05/14] First release --- .gitignore | 1 + ctabus.py | 10 ++++--- main.py | 88 +++++++++++++++++++++++++++++++++++++++++++++--------- search.py | 16 ++++++++-- 4 files changed, 94 insertions(+), 21 deletions(-) diff --git a/.gitignore b/.gitignore index 1a4bdfd..7e6f6e9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ /cta_api_key /output +/test.py __pycache__ *.pyc *_out.json diff --git a/ctabus.py b/ctabus.py index daca7a6..a14e39b 100644 --- a/ctabus.py +++ b/ctabus.py @@ -9,11 +9,13 @@ def get_data(type,api_key = api,**args): args['key'] = api_key args['format'] = 'json' url = base_url.format(type = type,query = urlencode(args)) - print(url) - input() response = get(url) - data = json.loads(response.text) - return data['bustime-response'] + data = json.loads(response.text)['bustime-response'] + try: + data['error'] + raise Exception(str(data["error"])) + except KeyError: + return data def get_times(stop_id,api_key = api): return get_data('getpredictions',api_key,stpid=stop_id) diff --git a/main.py b/main.py index 9365c9e..7601c2a 100644 --- a/main.py +++ b/main.py @@ -1,11 +1,10 @@ -# from argparse import parser +import argparse from print2d import print2d import re -# parser = argparse.ArgumentParser(prog = 'ctabus') -# parser.add_argument('arg',metavar = 'stop-id | cross streets') -# parser.add_argument('-r','--route',default = None) -# parser.add_argument('-d','--direction',default = None) -# args = parser.parse_args() +import ctabus +from dateutil.parser import parse as date_parse +import datetime +from search import Search,StopSearch def numb_sort(str): n = 40 try: @@ -14,6 +13,33 @@ def numb_sort(str): print(str) raise E +def pprint_delta(delta): + delta = str(delta) + days= None + s1 = delta.split(', ') + if len(s1) > 1: + days,time = s1 + else: + time = s1[0] + time = time.split('.')[0] + hour,minute,second = map(int,time.split(':')) + time = '' + if hour: + time += f'{hour} hour' + ('s' if hour != 1 else '') + if minute: + if time and not time.endswith(', '): + time += ', ' + time += f'{minute} minute' + ('s' if minute != 1 else '') + if second: + if time and not time.endswith(', '): + time += ', ' + time += f'{second} second' + ('s' if second != 1 else '') + ret = '' + if days: + ret = days + ', ' if time else '' + ret += time + return ret + def gen_list(objs,data,*displays,key = None,sort = 0,num_pic = True): k = displays[sort] display_data = {obj[k]:obj[data] for obj in objs} @@ -23,7 +49,7 @@ def gen_list(objs,data,*displays,key = None,sort = 0,num_pic = True): [ [obj[d] for d in displays] for obj in objs ], - key = lambda row: key(row[sort]) + key = lambda row: key(row[sort]) if key else row[sort] ) if num_pic: display = [[i] + data for i,data in enumerate(display)] @@ -54,11 +80,45 @@ def gen_list(objs,data,*displays,key = None,sort = 0,num_pic = True): pass return ret - +config = '''{delta} ({t}) +{route} - {end} ({direction})''' if __name__ == "__main__": - import json - with open('stops_out.json') as file: - d= json.load(file) - - d = d['stops'] - print(gen_list(d,'stpid','stpnm',key=numb_sort,num_pic=True)) + parser = argparse.ArgumentParser(prog = 'ctabus') + parser.add_argument('arg',nargs = '+',metavar = '(stop-id | cross streets)') + parser.add_argument('-r','--route',default = None) + parser.add_argument('-d','--direction',default = None) + args = parser.parse_args() + args.arg = ' '.join(args.arg) + print(args) + if not args.arg.isdecimal(): + #routes + if not args.route: + data = ctabus.get_routes()['routes'] + route = gen_list(data,'rt','rt','rtnm',num_pic = False,key=numb_sort) + else: + route = args.route + data = ctabus.get_directions(route)['directions'] + #direction + if not args.direction: + direction = gen_list(data,'dir','dir') + else: + s = Search(args.direction) + direction = sorted((obj['dir'] for obj in data),key = s)[0] + #direction + stops = ctabus.get_stops(route,direction)['stops'] + s = StopSearch(args.arg) + stop_id = gen_list(stops,'stpid','stpnm',key = s) + else: + stop_id = args.arg + times = ctabus.get_times(stop_id)['prd'] + today = datetime.datetime.today() + for time in times: + arrival = date_parse(time['prdtm']) + delta = pprint_delta(arrival-today) + t = arrival.strftime('%H:%M:%S') + route = time['rt'] + direction = time['rtdir'] + end = time['des'] + print( + config.format(**globals()),end= '\n'*2 + ) diff --git a/search.py b/search.py index f0dd163..03ea6c9 100644 --- a/search.py +++ b/search.py @@ -1,8 +1,19 @@ from editdistance import eval as editdistance import re import json -class StopSearch: +class Search: def __init__(self,query): + self.raw_lower = query.lower() + def __call__(self,arg): + arg = arg.lower() + return editdistance(self.raw_lower,arg) + def __str__(self): + print(self.raw_lower) + def __repr__(self): + return str(self) +class StopSearch(Search): + def __init__(self,query): + super().__init__(query) query = query.lower() parts = re.split(r' ?(?:(? Date: Thu, 20 Sep 2018 19:39:18 -0500 Subject: [PATCH 06/14] Removed uneccisary prints and updated requirements.txt; fixed cta_api_key not in cwd --- ctabus.py | 3 ++- main.py | 1 - requirements.txt | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/ctabus.py b/ctabus.py index a14e39b..833b05a 100644 --- a/ctabus.py +++ b/ctabus.py @@ -1,7 +1,8 @@ from urllib.parse import urlencode from requests import get import json -with open('cta_api_key') as file: +import os.path as osp +with open(osp.join(osp.dirname(__file__),'cta_api_key')) as file: api = file.read() def get_data(type,api_key = api,**args): diff --git a/main.py b/main.py index 7601c2a..cd50599 100644 --- a/main.py +++ b/main.py @@ -89,7 +89,6 @@ if __name__ == "__main__": parser.add_argument('-d','--direction',default = None) args = parser.parse_args() args.arg = ' '.join(args.arg) - print(args) if not args.arg.isdecimal(): #routes if not args.route: diff --git a/requirements.txt b/requirements.txt index 414733f..231acec 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,3 @@ editdistance -requests \ No newline at end of file +requests +python-dateutil \ No newline at end of file From 9ba087de9e1e2e30e494f39fd367aae76e96f046 Mon Sep 17 00:00:00 2001 From: Raphael Roberts Date: Thu, 20 Sep 2018 19:48:28 -0500 Subject: [PATCH 07/14] added stop_id to printed stuff --- .gitignore | 1 + main.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 7e6f6e9..b572212 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +/release /cta_api_key /output /test.py diff --git a/main.py b/main.py index cd50599..6b6f616 100644 --- a/main.py +++ b/main.py @@ -80,7 +80,7 @@ def gen_list(objs,data,*displays,key = None,sort = 0,num_pic = True): pass return ret -config = '''{delta} ({t}) +config = '''{delta} ({t}) stop {stop_id} {route} - {end} ({direction})''' if __name__ == "__main__": parser = argparse.ArgumentParser(prog = 'ctabus') From 18100932dc9b6947ebf8dd2f3af965613b0626b7 Mon Sep 17 00:00:00 2001 From: Raphael Roberts Date: Wed, 26 Sep 2018 01:26:22 -0500 Subject: [PATCH 08/14] Added newline at end if interactive for less bug; changed config --- .gitignore | 1 + main.py | 8 ++++++-- print2d.py | 2 ++ 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index b572212..647df45 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ /release /cta_api_key +/ctabus /output /test.py __pycache__ diff --git a/main.py b/main.py index 6b6f616..8793657 100644 --- a/main.py +++ b/main.py @@ -80,8 +80,11 @@ def gen_list(objs,data,*displays,key = None,sort = 0,num_pic = True): pass return ret -config = '''{delta} ({t}) stop {stop_id} -{route} - {end} ({direction})''' +config = '''\ +{route} - {end} ({direction}) +{nm}, stop {stop_id} +{delta} ({t})\ +''' if __name__ == "__main__": parser = argparse.ArgumentParser(prog = 'ctabus') parser.add_argument('arg',nargs = '+',metavar = '(stop-id | cross streets)') @@ -118,6 +121,7 @@ if __name__ == "__main__": route = time['rt'] direction = time['rtdir'] end = time['des'] + nm = time['stpnm'] print( config.format(**globals()),end= '\n'*2 ) diff --git a/print2d.py b/print2d.py index bf3326a..39a545b 100644 --- a/print2d.py +++ b/print2d.py @@ -36,6 +36,8 @@ def print2d(l,datetime_format = "%A, %B %e, %Y %H:%M:%S",seperator= ' | ',spacer if bottom: final = '\n'.join((bottom,final,bottom)) if interactive: + if not bottom: + final += '\n' pager(final) else: return final \ No newline at end of file From 8f9971b5913e921adcc42e0bd797214f944199b3 Mon Sep 17 00:00:00 2001 From: rlbr Date: Wed, 26 Sep 2018 10:25:13 -0500 Subject: [PATCH 09/14] sorted times --- main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.py b/main.py index 8793657..5620b14 100644 --- a/main.py +++ b/main.py @@ -114,7 +114,7 @@ if __name__ == "__main__": stop_id = args.arg times = ctabus.get_times(stop_id)['prd'] today = datetime.datetime.today() - for time in times: + for time in sorted(times,key = lambda t: t["prdtm"]): arrival = date_parse(time['prdtm']) delta = pprint_delta(arrival-today) t = arrival.strftime('%H:%M:%S') From 00e7265e30efa0b2a4096af5469061a60dcdfd1d Mon Sep 17 00:00:00 2001 From: Raphael Roberts Date: Wed, 26 Sep 2018 12:47:27 -0500 Subject: [PATCH 10/14] Results where original query is in result bumps it to the top; added "feeling lucky" option --- ctabus.py | 8 ++++---- main.py | 14 +++++++++----- print2d.py | 8 ++++---- search.py | 4 +++- 4 files changed, 20 insertions(+), 14 deletions(-) diff --git a/ctabus.py b/ctabus.py index 833b05a..8c3175c 100644 --- a/ctabus.py +++ b/ctabus.py @@ -17,16 +17,16 @@ def get_data(type,api_key = api,**args): raise Exception(str(data["error"])) except KeyError: return data - + def get_times(stop_id,api_key = api): return get_data('getpredictions',api_key,stpid=stop_id) - + def get_routes(api_key = api): return get_data('getroutes',api_key) - + def get_directions(route,api_key = api): return get_data('getdirections',api_key,rt=route) - + def get_stops(route,direction,api_key = api): return get_data('getstops',api_key,rt = route,dir=direction) diff --git a/main.py b/main.py index 8793657..c128523 100644 --- a/main.py +++ b/main.py @@ -12,7 +12,7 @@ def numb_sort(str): except Exception as E: print(str) raise E - + def pprint_delta(delta): delta = str(delta) days= None @@ -39,7 +39,7 @@ def pprint_delta(delta): ret = days + ', ' if time else '' ret += time return ret - + def gen_list(objs,data,*displays,key = None,sort = 0,num_pic = True): k = displays[sort] display_data = {obj[k]:obj[data] for obj in objs} @@ -53,7 +53,7 @@ def gen_list(objs,data,*displays,key = None,sort = 0,num_pic = True): ) if num_pic: display = [[i] + data for i,data in enumerate(display)] - + opts = { 'spacer':' ', 'seperator':' ', @@ -79,7 +79,7 @@ def gen_list(objs,data,*displays,key = None,sort = 0,num_pic = True): except KeyError: pass return ret - + config = '''\ {route} - {end} ({direction}) {nm}, stop {stop_id} @@ -90,6 +90,7 @@ if __name__ == "__main__": parser.add_argument('arg',nargs = '+',metavar = '(stop-id | cross streets)') parser.add_argument('-r','--route',default = None) parser.add_argument('-d','--direction',default = None) + parser.add_argument('-l','--lucky',action='store_true',help = 'picks first result') args = parser.parse_args() args.arg = ' '.join(args.arg) if not args.arg.isdecimal(): @@ -109,7 +110,10 @@ if __name__ == "__main__": #direction stops = ctabus.get_stops(route,direction)['stops'] s = StopSearch(args.arg) - stop_id = gen_list(stops,'stpid','stpnm',key = s) + if args.lucky: + stop_id = sorted(stops,key=lambda stop: s(stop['stpnm']))[0]['stpid'] + else: + stop_id = gen_list(stops,'stpid','stpnm',key = s) else: stop_id = args.arg times = ctabus.get_times(stop_id)['prd'] diff --git a/print2d.py b/print2d.py index 39a545b..3efee86 100644 --- a/print2d.py +++ b/print2d.py @@ -7,7 +7,7 @@ def str_coerce(s,**kwargs): return str(s) def print2d(l,datetime_format = "%A, %B %e, %Y %H:%M:%S",seperator= ' | ',spacer = ' ',bottom = '=',l_end = '|',r_end = '|',interactive = False): l = [[str_coerce(s,datetime_format = datetime_format) for s in row] for row in l] - + max_col = [] for row in l: for i,col in enumerate(row): @@ -15,18 +15,18 @@ def print2d(l,datetime_format = "%A, %B %e, %Y %H:%M:%S",seperator= ' | ',spacer max_col[i] = max(max_col[i],len(col)) except IndexError: max_col.append(len(col)) - + fmt_row = '{content}' if l_end: fmt_row = f'{l_end} ' + fmt_row if r_end: fmt_row = fmt_row + f' {r_end}' - + done = [] for row in l: content = seperator.join(col.ljust(max_col[i],spacer if i < len(row)-1 or r_end else ' ') for i,col in enumerate(row)) done.append(fmt_row.format(content = content)) - + if bottom: bottom = bottom*len(done[0]) row_sep = ('\n'+bottom+'\n') diff --git a/search.py b/search.py index 03ea6c9..70bc920 100644 --- a/search.py +++ b/search.py @@ -28,6 +28,8 @@ class StopSearch(Search): if paren: paren = paren.group('data') ret.append(editdistance(self.query,paren)) + if self.raw_lower in stop: + ret = (item - 100 for item in ret) return min( ret ) @@ -40,4 +42,4 @@ if __name__ == "__main__": names = [stop['stpnm'] for stop in data['stops']] while True: q = StopSearch(input('Search: ')) - print('\n'.join(sorted(names,key=q))) \ No newline at end of file + print('\n'.join(sorted(names,key=q)),end='\n'*3) \ No newline at end of file From b8081fee832d654be0f2d9adcdb93e390b8d7a32 Mon Sep 17 00:00:00 2001 From: Raphael Roberts Date: Thu, 27 Sep 2018 23:27:40 -0500 Subject: [PATCH 11/14] removed request dependency --- ctabus.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ctabus.py b/ctabus.py index 8c3175c..68c0dcb 100644 --- a/ctabus.py +++ b/ctabus.py @@ -1,5 +1,5 @@ from urllib.parse import urlencode -from requests import get +from urllib.request import urlopen import json import os.path as osp with open(osp.join(osp.dirname(__file__),'cta_api_key')) as file: @@ -10,8 +10,8 @@ def get_data(type,api_key = api,**args): args['key'] = api_key args['format'] = 'json' url = base_url.format(type = type,query = urlencode(args)) - response = get(url) - data = json.loads(response.text)['bustime-response'] + response = urlopen(url) + data = json.load(response)['bustime-response'] try: data['error'] raise Exception(str(data["error"])) From 3999d6ff07b7053c8f291bcc9fe54584b533de3d Mon Sep 17 00:00:00 2001 From: rlbr Date: Mon, 1 Oct 2018 13:13:24 -0500 Subject: [PATCH 12/14] errors log to file and using edlib instead of editdistance --- .gitignore | 3 ++- main.py | 3 +++ requirements.txt | 2 +- search.py | 4 +++- 4 files changed, 9 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 647df45..8efb089 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,5 @@ __pycache__ *.pyc *_out.json *.pdf -*.bat \ No newline at end of file +*.bat +stderr.log \ No newline at end of file diff --git a/main.py b/main.py index 651ea01..001ef13 100644 --- a/main.py +++ b/main.py @@ -4,6 +4,8 @@ import re import ctabus from dateutil.parser import parse as date_parse import datetime +import sys +import os.path as osp from search import Search,StopSearch def numb_sort(str): n = 40 @@ -92,6 +94,7 @@ if __name__ == "__main__": parser.add_argument('-d','--direction',default = None) parser.add_argument('-l','--lucky',action='store_true',help = 'picks first result') args = parser.parse_args() + sys.stderr = open(osp.join(osp.dirname(__file__),'stderr.log'),'w') args.arg = ' '.join(args.arg) if not args.arg.isdecimal(): #routes diff --git a/requirements.txt b/requirements.txt index 231acec..1dec4c5 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,3 @@ -editdistance +edlib requests python-dateutil \ No newline at end of file diff --git a/search.py b/search.py index 70bc920..4485405 100644 --- a/search.py +++ b/search.py @@ -1,4 +1,6 @@ -from editdistance import eval as editdistance +import edlib +def editdistance(a,b): + return edlib.align(a,b)['editDistance'] import re import json class Search: From b73b6a0ab8a45c1f83395166980b4f2f3ba5e6b2 Mon Sep 17 00:00:00 2001 From: Raphael Roberts Date: Sat, 6 Oct 2018 04:18:38 -0500 Subject: [PATCH 13/14] test --- ctabus.py | 1 + 1 file changed, 1 insertion(+) diff --git a/ctabus.py b/ctabus.py index 68c0dcb..1e2b88b 100644 --- a/ctabus.py +++ b/ctabus.py @@ -30,3 +30,4 @@ def get_directions(route,api_key = api): def get_stops(route,direction,api_key = api): return get_data('getstops',api_key,rt = route,dir=direction) +# \ No newline at end of file From cd613f30dafaf24c0c8c1e8f2e5627042b00bb48 Mon Sep 17 00:00:00 2001 From: rlbr Date: Wed, 10 Oct 2018 13:58:32 -0500 Subject: [PATCH 14/14] updated requirements.txt --- requirements.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 1dec4c5..db25db4 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,2 @@ edlib -requests python-dateutil \ No newline at end of file