flightCal.py
changeset 10: 8f2442d0cea3
parent 6:f468f14f043f
child 71:2db4775b7b89
manifest: 8f2442d0cea3
author: Dan Connolly http://www.w3.org/People/Connolly/
date: Sat Jun 23 22:15:34 2007 -0500 (10 months ago)
permissions: -rw-r--r--
handle KLM in fltlink()
        1 """
        2 flightCal -- make hCalendar from text flight info
        3 
        4 :Author: `Dan Connolly`_
        5 :Copyright: `W3C Open Source License`_ Share and enjoy.
        6 
        7 .. _Dan Connolly: http://www.w3.org/People/Connolly/
        8 .. _W3C Open Source License: http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231
        9 
       10 
       11 Usage
       12 -----
       13 
       14 Run a la::
       15 
       16    python title <flightinfo.txt >flightinfo.html
       17 
       18 
       19 where flightinfo.txt is a text flight itinerary
       20 in a format produced, I think, by Sabre_.
       21 
       22 .. _Sabre: http://en.wikipedia.org/wiki/Sabre_%28computer_system%29
       23 
       24 
       25 Testing and Colophon
       26 --------------------
       27 
       28 The examples in the docstrings below are executable doctest_ unit
       29 tests.  Check them a la::
       30 
       31   python flightCal.py --test
       32 
       33 @@with files flttbl.xml and Airports in the current directory.
       34 
       35 .. _doctest: http://www.python.org/doc/lib/module-doctest.html
       36 
       37 This module is documented in rst_ format for use with epydoc_.
       38 
       39 .. _epydoc: http://epydoc.sourceforge.net/
       40 .. _rst: http://docutils.sourceforge.net/docs/user/rst/quickstart.html
       41 
       42 """
       43 
       44 import re
       45 from genshi.template import MarkupTemplate # http://genshi.edgewall.org/
       46 
       47 import fltstxt, zonetab, aptdata
       48 
       49 __docformat__ = 'restructuredtext en'
       50 
       51 
       52 def main(argv, template="flttbl.xml"):
       53     import sys
       54     web = webarg(argv)
       55     zones=list(zonetab.timezones(exclude=["Indiana"]))
       56     sys.stdout.write(convert(sys.stdin, template, web, zones, argv[1]))
       57 
       58 
       59 # Sabre seems to have its own way of naming airports.
       60 # I can't find a list of them online.
       61 # So in a file called Airports@@, we list them, a la:
       62 # BOS BOSTON
       63 # CDG PARIS DE GAULLE
       64 # ...
       65 Airports = [s.strip().split(" ", 1) for s in file("Airports")]
       66 
       67 
       68 
       69 
       70 def progress(*args):
       71     import sys
       72     for a in args:
       73         sys.stderr.write('%s ' % a)
       74     sys.stderr.write("\n")
       75 
       76     
       77 
       78 def offsettz(zones, when, where):
       79     """Use latitude/longitude find utc offset for a a local time.
       80     
       81     >>> offsettz(zonetab.timezones(),
       82     ...          {'float': '2006-10-06T15:50:00'},
       83     ...          {'geo': {'longitude': -94, 'latitude': 39}})
       84     '2006-10-06T15:50:00-05:00'
       85 
       86     """
       87     try:
       88 	lat = where['geo']['latitude']
       89 	lon = where['geo']['longitude']
       90     except KeyError:
       91 	return
       92     else:
       93         tz = zonetab.nearest_tz(lat, lon, zones)[2]
       94 	out =  zonetab.stdtime(tz, when['float'])
       95 	when['date_time'] =  out
       96     return out
       97 
       98 
       99 def iata_nick(card):
      100     """Set nickname to the iata code
      101     if the org field of a card is a known airport name
      102     """
      103     org = card['org']['organization_name']
      104     for iata, n in Airports:
      105         if org == n:
      106             card['nickname'] = {'text': iata}
      107             return iata
      108     raise KeyError
      109 
      110 def fltlink(carrier, num):
      111     """
      112 
      113     >>> fltlink('AMERICAN AIRLINES', 1557)
      114     '@@'
      115     
      116     """
      117 
      118     if carrier=='AMERICAN AIRLINES':
      119         return "http://aa2go.com/index.php?page=status&sub=results&Fn=%s" % num
      120     # iata airline codes
      121     # @@todo: look these up from wikipedia. hmm... how to correlate names?
      122     airlines = {'AMERICAN AIRLINES': 'AA',
      123 
      124                 # http://en.wikipedia.org/wiki/Midwest_Airlines
      125                 'MIDWEST AIRLINES': 'YX',
      126                 'UNITED AIRLINES': 'UA',
      127                 # http://en.wikipedia.org/wiki/Delta_Air_Lines
      128                 'DELTA AIR LINES INC': 'DL',
      129                 # http://en.wikipedia.org/wiki/US_Airways
      130                 'US AIRWAYS': 'US',
      131                 # http://en.wikipedia.org/wiki/KLM
      132                 'KLM ROYAL DUTCH': 'KL'
      133                 }
      134     airlineCode = airlines[carrier]
      135     action = 'https://bwi.flightview.com/fvSabreVT/fvCPL.exe'
      136     params = {'AL': airlineCode,
      137               'acid': str(num),
      138               'qtype': 'htm',
      139               'Find1': 'Track+Flight',
      140               'vthost': '1W'
      141               }
      142     q = '&'.join(['%s=%s' % (n, v) for n, v in params.iteritems()])
      143     return "%s?%s" % (action, q)
      144 
      145 
      146 def _test():
      147     import doctest
      148     doctest.testmod()
      149 
      150 def convert(infp, template, web, zones, title):
      151     events = list(fltstxt.flights(infp))
      152 
      153     # look up airport lat/long; fill in time offsets
      154     for flt in events:
      155         flt['url'] = fltlink(flt['carrier'], flt['FLT']) #@@
      156         for apt in [flt['location'][x] for x in ['lv', 'ar']]:
      157             try:
      158                 iata_nick(apt)
      159             except KeyError:
      160                 progress("unrecognized airport", apt['fn']['text'])
      161             else:
      162                 if web:    
      163                     aptdata.airportCard(web,
      164                                         apt['nickname']['text'], apt)
      165         offsettz(zones, flt['dtstart'], flt['location']['lv'])
      166         offsettz(zones, flt['dtend'], flt['location']['ar'])
      167 
      168 
      169     tmpl = MarkupTemplate(file(template).read())
      170     stream = tmpl.generate(title=title,
      171                            events=events)
      172     return stream.render()
      173 
      174 
      175 def webarg(argv):
      176     web = None
      177     if '--online' in sys.argv:
      178 	web = aptdata.WebCache("wikipedia-cache").get
      179 	del argv[argv.index('--online')]
      180     return web
      181 
      182 
      183 if __name__ == '__main__':
      184     import sys
      185     if '--test' in sys.argv:
      186         _test()
      187     else:
      188 	main(sys.argv)
      189