Update of /cvsroot/freevo/freevo/src/util
In directory sc8-pr-cvs1:/tmp/cvs-serv31851/src/util

Modified Files:
        pymetar.py 
Log Message:
Merge of the new version of the pymetar library from upstream.

Changes:
    * (to upstream) Added back timeoutsocket code which upstream doesn't use,
        and removed some print statements
    * We now use the pymetar Fahrenheit function instead of doing it in the idle
        bar; it was already being calculated by pymetar anyway.
    * When we don't have a temperature, use '?' instead of '0' which is misleading
        since it's Winter now :) 
    * minor cleanups




Index: pymetar.py
===================================================================
RCS file: /cvsroot/freevo/freevo/src/util/pymetar.py,v
retrieving revision 1.1
retrieving revision 1.2
diff -C2 -d -r1.1 -r1.2
*** pymetar.py  27 Oct 2003 20:11:46 -0000      1.1
--- pymetar.py  22 Nov 2003 21:06:41 -0000      1.2
***************
*** 19,66 ****
  # By reading this code you agree not to ridicule the author =)
  
! import string
  import re
  import urllib2
! import types
! import math, fpformat
  
- __author__ = "[EMAIL PROTECTED]"
  
! __version__ = "0.5"
  
! __doc__ = """Pymetar v%s (c) 2002 Tobias Klausman
  
  Pymetar is a python module and command line tool designed to fetch Metar
! reports from the NOAA (http://www.noaa.gov) and allow access to the included
! weather information.
  
! This program is free software; you can redistribute it and/or modify it under
! the terms of the GNU General Public License as published by the Free Software
! Foundation; either version 2 of the License, or (at your option) any later
! version.
  
! This program is distributed in the hope that it will be useful, but WITHOUT ANY
! WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
! PARTICULAR PURPOSE.  See the GNU General Public License for more details.
  
! You should have received a copy of the GNU General Public License along with
! this program; if not, write to the Free Software Foundation, Inc., 59 Temple
! Place, Suite 330, Boston, MA 02111-1307, USA.
  
  Please e-mail bugs to: %s""" % (__version__, __author__)
  
- import sys
- if float(sys.version[0:3]) >= 2.3:
-     import socket
-     socket.setdefaulttimeout(10)
- else:
-     try:
-         import timeoutsocket # http://www.timo-tasi.org/python/timeoutsocket.py
-         timeoutsocket.setDefaultSocketTimeout(10)
-     except ImportError:
-         pass
  
  
- #
  # What a boring list to type !
  #
--- 19,83 ----
  # By reading this code you agree not to ridicule the author =)
  
! # When reading this code you'll noctice that not everything is parsed
! # from the raw METAR info as supplied with the report. Before you start
! # flaming the authors, please read the FHM-1 spec and guess how hairy a
! # parser for that format would be. As a side note, the reference 
! # implementation of the parser is written in... FORTRAN. Now stop crying.
! 
! import fpformat
! import math
  import re
+ import string
  import urllib2
! import sys
! if float(sys.version[0:3]) >= 2.3:
!     import socket
!     socket.setdefaulttimeout(10)
! else:
!     try:
!         import timeoutsocket # http://www.timo-tasi.org/python/timeoutsocket.py
!         timeoutsocket.setDefaultSocketTimeout(10)
!     except ImportError:
!         pass
  
  
! __author__ = "[EMAIL PROTECTED]"
  
! __version__ = "0.6b"
! 
! __doc__ = """Pymetar v%s (c) 2002, 2003 Tobias Klausman
  
  Pymetar is a python module and command line tool designed to fetch Metar
! reports from the NOAA (http://www.noaa.gov) and allow access to the
! included weather information.
  
! This program is free software; you can redistribute it and/or modify it
! under the terms of the GNU General Public License as published by the
! Free Software Foundation; either version 2 of the License, or (at your
! option) any later version.
  
! This program is distributed in the hope that it will be useful, but
! WITHOUT ANY WARRANTY; without even the implied warranty of
! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
! General Public License for more details.
  
! You should have received a copy of the GNU General Public License along
! with this program; if not, write to the Free Software Foundation, Inc.,
! 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
  
  Please e-mail bugs to: %s""" % (__version__, __author__)
  
  
+ CLOUD_RE_STR= r"^(CLR|SKC|BKN|SCT|FEW|OVC)([0-9]{3})?$"
+ COND_RE_STR = 
r"^(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)$"
+ 
+ class EmptyReportException(Exception):
+     def __init__(self, args=None):
+         self.args=args
+ 
+ class EmptyIDException(Exception):
+     def __init__(self, args=None):
+         self.args=args
  
  # What a boring list to type !
  #
***************
*** 356,493 ****
                      }
  
! #
! # RegExps to extract the different parts from the Metar encoded report
! TIME_RE_STR = r"^([0-9]{6})Z$"
! WIND_RE_STR = r"^(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?KT$"
! VIS_RE_STR  = r"^(([0-9]?[0-9])|(M?1/[0-9]?[0-9]))SM$"
! CLOUD_RE_STR= r"^(CLR|SKC|BKN|SCT|FEW|OVC)([0-9]{3})?$"
! TEMP_RE_STR = r"^(M?[0-9][0-9])/(M?[0-9][0-9])$"
! PRES_RE_STR = r"^(A|Q)([0-9]{4})$"
! COND_RE_STR = 
r"^(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)$"
! 
! class MetarReport:
! 
!     """
!     This class provides a means to download and parse the decoded METAR reports
!     from http://weather.noaa.gov/
! 
!     In order to find the report relevant for you, find the closest station at
!     http://www.nws.noaa.gov/oso/siteloc.shtml and feed its 4-letter station
!     code to fetchMetarReport(), case does not matter.
! 
!     All methods return metric values, no matter what the station provides. The
!     conversion factors were taken from the excellent "units" program.
! 
!     If None is returned that means the information wasn't available or could
!     not be parsed. If you have the suspicion that failure to parse an
!     information was this libs fault, please save the report generating the
!     error send it to me with a few lines detailing the problem. Thanks!
!     """
! 
!     def match_WeatherPart(self, regexp) :
!         """
!         Returns the matching part of the encoded Metar report.  
!         regexp: the regexp needed to extract this part.  
!         Returns the first matching string or None.  
!         WARNING: Some Metar reports may contain several matching strings, only
!         the first one is taken into account, e.g. FEW020 SCT075 BKN053 
!         """
!         if self.code is not None :
!             rg = re.compile(regexp)
!             for wpart in self.getRawMetarCode().split() :
!                 match = rg.match(wpart)
!                 if match :
!                     return match.string[match.start(0) : match.end(0)]
! 
!     def extractSkyConditions(self) :
!         """
!         Extracts sky condition information from the encoded report.  Returns a
!         tuple containing the description of the sky conditions as a string and
!         a suggested pixmap name for an icon representing said sky condition.
!         """
!         wcond = self.match_WeatherPart(COND_RE_STR)
!         if wcond is not None :
!             if (len(wcond) > 3) and (wcond.startswith('+') or wcond.startswith('-')) 
:
!                 wcond = wcond[1:]
!             if wcond.startswith('+') or wcond.startswith('-') :
!                 pphen = 1
!             elif len(wcond) < 4 :
!                 pphen = 0
!             else :
!                 pphen = 2
!             squal = wcond[:pphen]
!             sphen = wcond[pphen : pphen + 4]
!             phenomenon = _WeatherConditions.get(sphen, None)
!             if phenomenon is not None :
!                 (name, pixmap, phenomenon) = phenomenon
!                 pheninfo = phenomenon.get(squal, name)
!                 if type(pheninfo) != types.TupleType :
!                     return (pheninfo, pixmap)
!                 else :
!                     # contains pixmap info
!                     return pheninfo
! 
!     def parseLatLong(self, latlong):
!         """
!         Parse Lat or Long in METAR notation into float values. N and E are +, S
!         and W are -. Expects one positional string and returns one float value.
!         """
!         # I know, I could invert this if and put
!         # the rest of the function into its block,
!         # but I find this to be more readable
!         if latlong is None: return None
! 
!         s = string.strip(string.upper(latlong))
!         elms = string.split(s,'-')
!         ud = elms[-1][-1]
!         elms[-1] = elms[-1][:-1]
!         elms = map(string.atoi, elms)
!         coords = 0.0
!         elen = len(elms)
!         if elen > 2:
!             coords = coords + float(elms[2])/3600.0
! 
!         if elen > 1:
!             coords = coords + float(elms[1])/60.0
! 
!         coords=coords + float(elms[0])
! 
!         if ud in ('W','S'):
!             coords=-1.0*coords
! 
!         f,i=math.modf(coords)
  
!         if elen > 2:
!             f=float(fpformat.sci(f,4))
!         elif elen > 1:
!             f=float(fpformat.sci(f,2))
!         else:
!             f=0.0
  
!         return f+i
  
!     def extractCloudInformation(self) :
!         """
!         Extracts cloud information.  returns None or a tuple (sky type as a
!         string of text and suggested pixmap name)
!         """   
!         wcloud = self.match_WeatherPart(CLOUD_RE_STR)
!         if wcloud is not None :
!             stype = wcloud[:3]
!             if (stype == "CLR") or (stype == "SKC") :
!                 return ("Clear sky", "sun")
!             elif stype == "BKN" :
!                 return ("Broken clouds", "suncloud")
!             elif stype == "SCT" :
!                 return ("Scattered clouds", "suncloud")
!             elif stype == "FEW" :
!                 return ("Few clouds", "suncloud")
!             elif stype == "OVC" :
!                 return ("Overcast", "cloud")
  
      def getFullReport(self):
!         """
!         Return the complete weather report.
!         """
          return self.fullreport
  
--- 373,427 ----
                      }
  
! class WeatherReport:
!     """Incorporates both the unparsed textual representation of the
!     weather report and the parsed values as soon as they are filled 
!     in by ReportParser."""
  
!     def _ClearAllFields(self):
!         """Clear all fields values."""
!         # until finished, report is invalid
!         self.valid = 0
!         # Clear all
!         self.givenstationid=None
!         self.fullreport=None
!         self.temp=None
!         self.windspeed=None
!         self.winddir=None
!         self.vis=None
!         self.dewp=None
!         self.humid=None
!         self.press=None
!         self.code=None
!         self.weather=None
!         self.sky=None
!         self.fulln=None
!         self.cycle=None
!         self.windcomp=None
!         self.rtime=None
!         self.pixmap=None
!         self.latitude=None
!         self.longitude=None
!         self.altitude=None
!         self.stat_city=None
!         self.stat_country=None
!         self.reporturl=None
!         self.latf=None
!         self.longf=None
  
!     def __init__(self, MetarStationCode = None):
!         """Clear all fields and fill in wanted station id."""
!         self._ClearAllFields()
!         self.givenstationid=MetarStationCode
  
!     def metar_to_iso8601(self, metardate) :
!         """Convert a metar date to an ISO8601 date."""
!         if metardate is not None:
!             (date, hour, tz) = metardate.split()
!             (year, month, day) = date.split('.')
!             # assuming tz is always 'UTC', aka 'Z'
!             return "%s-%s-%s %s:%s:00Z"%(year, month, day, hour[:2], hour[2:4])
  
      def getFullReport(self):
!         """ Return the complete weather report.  """
          return self.fullreport
  
***************
*** 598,605 ****
          """
          Return cycle value.
!         The cycle value is not the frequency or delay between observations but
!         the "time slot" in which the observation was made. There are 24 cycle
!         slots every day which usually last from N:45 to N+1:45. The cycle from
!         23:45 to 0:45 is cycle 0.
          """
          return self.cycle
--- 532,539 ----
          """
          Return cycle value.
!         The cycle value is not the frequency or delay between 
!         observations but the "time slot" in which the observation was made. 
!         There are 24 cycle slots every day which usually last from N:45 to 
!         N+1:45. The cycle from 23:45 to 0:45 is cycle 0.
          """
          return self.cycle
***************
*** 607,619 ****
      def getStationPosition(self):
          """
!         Return latitude, longitude and altitude above sea level of station as a
!         tuple. Some stations don't deliver altitude, for those, None is
!         returned as altitude.  The lat/longs are expressed as follows:
          xx-yyd
          where xx is degrees, yy minutes and d the direction.
!         Thus 51-14N means 51 degrees, 14 minutes north.  d may take the values
!         N, S for latitues and W, E for longitudes. Latitude and Longitude may
!         include seconds.  Altitude is always given as meters above sea level,
!         including a trailing M.
          Schipohl Int. Airport Amsterdam has, for example:
          ('52-18N', '004-46E', '-2M')
--- 541,553 ----
      def getStationPosition(self):
          """
!         Return latitude, longitude and altitude above sea level of station
!         as a tuple. Some stations don't deliver altitude, for those, None 
!         is returned as altitude.  The lat/longs are expressed as follows:
          xx-yyd
          where xx is degrees, yy minutes and d the direction.
!         Thus 51-14N means 51 degrees, 14 minutes north.  d may take the 
!         values N, S for latitues and W, E for longitudes. Latitude and 
!         Longitude may include seconds.  Altitude is always given as meters 
!         above sea level, including a trailing M.
          Schipohl Int. Airport Amsterdam has, for example:
          ('52-18N', '004-46E', '-2M')
***************
*** 623,631 ****
          getStationPositionFloat() instead
          """
!         return (self.latitude, self.longitude, self.altitude)
  
      def getStationPositionFloat(self):
          """
!         Return latitude and longitude as float values in a tuple (lat,long,alt)
          """
          return (self.latf,self.longf,self.altitude)
--- 557,567 ----
          getStationPositionFloat() instead
          """
!         # convert self.altitude to string for consistency
!         return (self.latitude, self.longitude, "%s"%self.altitude)
  
      def getStationPositionFloat(self):
          """
!         Return latitude and longitude as float values in a 
!         tuple (lat,long,alt).
          """
          return (self.latf,self.longf,self.altitude)
***************
*** 661,665 ****
          Return Longitude as a float
          """
!         return (self.longf)
  
      def getStationAltitude(self) :
--- 597,601 ----
          Return Longitude as a float
          """
!         return self.longf
  
      def getStationAltitude(self) :
***************
*** 677,682 ****
      def getTime(self):
          """
!         Return the time when the observation was made.  Note that this is *not*
!         the time when the report was fetched by us
          Format:  YYYY.MM.DD HHMM UTC
          Example: 2002.04.01 1020 UTC
--- 613,618 ----
      def getTime(self):
          """
!         Return the time when the observation was made.  Note that this 
!         is *not* the time when the report was fetched by us
          Format:  YYYY.MM.DD HHMM UTC
          Example: 2002.04.01 1020 UTC
***************
*** 693,913 ****
      def getPixmap(self):
          """
!         Return a suggested pixmap name, without extension, depending on current
!         weather.
          """
          return self.pixmap
  
!     def metar_to_iso8601(self, metardate) :
!         """
!         Converts a metar date to an ISO8601 date.
!         """
!         if metardate is not None:
!             (date, hour, tz) = metardate.split()
!             (year, month, day) = date.split('.')
!             # assuming tz is always 'UTC', aka 'Z'
!             return "%s-%s-%s %s:%s:00Z" % (year, month, day, hour[:2], hour[2:4])
  
      def strreverse(self, str):
!         """
!         Reverses a string
!         """
          listr=list(str)
          listr.reverse()
!         return (string.join(listr,""))
  
!     def __init__(self, MetarStationCode = None):
          """
!         Get initial report if a station code is passed as a parameter,
!         otherwise initialize fields.
          """
!         if MetarStationCode is not None :
!             self.fetchMetarReport(MetarStationCode)
!         else :
!             self._ClearAllFields()
  
!     def _ClearAllFields(self):
          """
!         Clears all fields values.
          """
!         # until finished, report is invalid
!         self.valid = 0
!         # Clear all
!         self.fullreport=None
!         self.temp=None
!         self.windspeed=None
!         self.winddir=None
!         self.vis=None
!         self.dewp=None
!         self.humid=None
!         self.press=None
!         self.code=None
!         self.weather=None
!         self.sky=None
!         self.fulln=None
!         self.cycle=None
!         self.windcomp=None
!         self.rtime=None
!         self.pixmap=None
!         self.latitude=None
!         self.longitude=None
!         self.altitude=None
!         self.stat_city=None
!         self.stat_country=None
!         self.reportutl=None
!         self.latf=None
!         self.longf=None
  
!     def fetchMetarReport(self, station, 
baseurl="http://weather.noaa.gov/pub/data/observations/metar/decoded/";):
          """
!         Retrieve the decoded METAR report from the given base URL and parse it.
!         Fill the data properties in the class instance with the values found in
!         the report, converting them to metric values where necessary.
          """
!         self._ClearAllFields()
!         station=string.upper(station)
!         self.reporturl="%s%s.TXT" % (baseurl, station)
!         
!         # Honor HTTP_PROXY environment var
!         # Thanks to Davide Di Blasi for suggesting this
!         urllib2.install_opener(
!             urllib2.build_opener(urllib2.ProxyHandler, urllib2.HTTPHandler))
!         
!         fn=urllib2.urlopen(self.reporturl)
!         # Dump entire report in a variable
!         self.fullreport=fn.read()
  
!         # if fn.info().status is 0, everything seems to be in order
!         if not fn.info().status:
  
!             lines=string.split(self.fullreport,"\n")
  
!             for line in lines:
!                 # Most lines start with a Header and a colon
                  try:
!                     header,data=string.split(line,":",1)
                  except ValueError:
!                     header=data=line
  
!                 header=string.strip(header)
!                 data=string.strip(data)
  
!                 # The station identifier and location
!                 if (string.find(header,"("+station+")")!=-1):
!                     try:
!                         loc,p=string.split(data,"(",1)
!                         loc=string.strip(loc)
!                         rloc=self.strreverse(loc)
!                         rcoun,rcity=string.split(rloc,",",1)
!                     except ValueError:
!                         city=""
!                         coun=""
!                         p=data
                      try:
!                         id,lat,long,ht=string.split(p," ")
!                         ht = int(ht[:-1]) # skip the 'M' for meters
                      except ValueError:
!                         id,lat,long=string.split(p," ")
!                         ht=None
!                     self.stat_city=string.strip(self.strreverse(rcity))
!                     self.stat_country=string.strip(self.strreverse(rcoun))
!                     self.fulln=loc
!                     self.latitude = lat
!                     self.longitude = long
!                     self.latf=self.parseLatLong(lat)
!                     self.longf=self.parseLatLong(long)
!                     self.altitude = ht
  
!                 # The line containing the date/time of the report
!                 elif (string.find(data,"UTC")!=-1):
!                     local,rt=string.split(data,"/")
!                     self.rtime=string.strip(rt)
  
!                 # temperature
!                 elif (header=="Temperature"):
!                     t,i=string.split(data," ",1)
!                     self.temp=(float(t)-32)*(5.0/9.0)
  
!                 # wind direction and speed
!                 elif (header == "Wind"):
!                     if (string.find(data,"Calm")!=-1):
!                         self.windspeed=0.0
!                         self.winddir=None
!                         self.windcomp=None
!                     elif (string.find(data,"Variable")!=-1):
!                         v,a,speed,r=string.split(data," ",3)
!                         self.windspeed=(float(speed)*0.44704)
!                         self.winddir=None
!                         self.windcomp=None
!                     else:
!                         f,t,comp,deg,r,d,speed,r=string.split(data," ",7)
!                         self.winddir=int(deg[1:])
!                         self.windcomp=string.strip(comp)
!                         self.windspeed=(float(speed)*0.44704)
  
!                 # visibility
!                 elif (header=="Visibility"):
!                     for d in data.split() :
!                         try :
!                             self.vis = float(d)*1.609344
!                             break
!                         except ValueError :
!                             pass
  
!                 # dew point
!                 elif (header=="Dew Point"):
!                     dp,i=string.split(data," ",1)
!                     self.dewp=(float(dp)-32)*(5.0/9.0)
  
!                 # humidity
!                 elif (header=="Relative Humidity"):
!                     h,i=string.split(data,"%",1)
!                     self.humid=int(h)
  
!                 # pressure
!                 elif (header=="Pressure (altimeter)"):
!                     p,r=string.split(data," ",1)
!                     self.press=(float(p)*33.863886)
  
!                 # short weather description ("rain", "mist", ...)
!                 elif (header=="Weather"):
!                     self.weather=data
  
!                 # short description of sky cond.
!                 elif (header=="Sky conditions"):
!                     self.sky=data
  
!                 # the encoded weather report
!                 elif (header=="ob"):
!                     self.code=string.strip(data)
  
!                 # the cycle value describes the cycle in
!                 # which the observations were made
!                 elif (header=="cycle"):
!                     self.cycle=int(data)
  
!             # decode cloud and sky conditions informations from
!             # the raw report, this will suggest us a pixmap to use
!             # to graphically represent the weather.
!             cloudinfo = self.extractCloudInformation()
!             if cloudinfo is not None :
!                 (cloudinfo, cloudpixmap) = cloudinfo
!             else :
!                 (cloudinfo, cloudpixmap) = (None, None)
!             conditions = self.extractSkyConditions()
!             if conditions is not None :
!                 (conditions, condpixmap) = conditions
!             else :
!                 (conditions, condpixmap) = (None, None)
  
!             # fill the weather information
!             self.weather = self.weather or conditions or cloudinfo
  
!             # Pixmap guessed from general conditions has priority
!             # over pixmap guessed from clouds
!             self.pixmap = condpixmap or cloudpixmap
  
!             # report is complete
!             self.valid = 1
  
-         # Even if the report is bad, toss the fd
-         del fn
--- 629,953 ----
      def getPixmap(self):
          """
!         Return a suggested pixmap name, without extension, depending on 
!         current weather.
          """
          return self.pixmap
  
! 
! class ReportParser:
!     """Parse raw METAR data from a WeatherReport object into actual 
!     values and return the object with the values filled in."""
! 
!     def __init__(self, MetarReport=None):
!         """Set attribute Report as specified on instantation."""
!         self.Report=MetarReport
  
      def strreverse(self, str):
!         """Reverse a string"""
          listr=list(str)
          listr.reverse()
!         return "".join(listr)
  
!     def extractCloudInformation(self) :
          """
!         Extract cloud information. Return None or a tuple (sky type as a
!         string of text and suggested pixmap name)
!         """   
!         wcloud = self.match_WeatherPart(CLOUD_RE_STR)
!         if wcloud is not None :
!             stype = wcloud[:3]
!             if (stype == "CLR") or (stype == "SKC") :
!                 return ("Clear sky", "sun")
!             elif stype == "BKN" :
!                 return ("Broken clouds", "suncloud")
!             elif stype == "SCT" :
!                 return ("Scattered clouds", "suncloud")
!             elif stype == "FEW" :
!                 return ("Few clouds", "suncloud")
!             elif stype == "OVC" :
!                 return ("Overcast", "cloud")
!         else:
!             return None # Not strictly necessary
! 
!     def extractSkyConditions(self) :
          """
!         Extract sky condition information from the encoded report. Return 
!         a tuple containing the description of the sky conditions as a 
!         string and a suggested pixmap name for an icon representing said 
!         sky condition.
!         """
!         wcond = self.match_WeatherPart(COND_RE_STR)
!         if wcond is not None :
!             if (len(wcond)>3) and (wcond.startswith('+') or wcond.startswith('-')) :
!                 wcond = wcond[1:]
!             if wcond.startswith('+') or wcond.startswith('-') :
!                 pphen = 1
!             elif len(wcond) < 4 :
!                 pphen = 0
!             else :
!                 pphen = 2
!             squal = wcond[:pphen]
!             sphen = wcond[pphen : pphen + 4]
!             phenomenon = _WeatherConditions.get(sphen, None)
!             if phenomenon is not None :
!                 (name, pixmap, phenomenon) = phenomenon
!                 pheninfo = phenomenon.get(squal, name)
!                 if type(pheninfo) != types.TupleType :
!                     return (pheninfo, pixmap)
!                 else :
!                     # contains pixmap info
!                     return pheninfo
  
!     def match_WeatherPart(self, regexp) :
          """
!         Return the matching part of the encoded Metar report.  
!         regexp: the regexp needed to extract this part.  
!         Return the first matching string or None.  
!         WARNING: Some Metar reports may contain several matching 
!         strings, only the first one is taken into account!
          """
!         if self.Report.code is not None :
!             rg = re.compile(regexp)
!             for wpart in self.Report.getRawMetarCode().split() :
!                 match = rg.match(wpart)
!                 if match:
!                     return match.string[match.start(0) : match.end(0)]
  
!     def parseLatLong(self, latlong):
          """
!         Parse Lat or Long in METAR notation into float values. N and E 
!         are +, S and W are -. Expects one positional string and returns 
!         one float value.
          """
!         # I know, I could invert this if and put
!         # the rest of the function into its block,
!         # but I find it to be more readable this way
!         if latlong is None: return None
  
!         s=latlong.upper().strip()
!         elms = s.split('-')
!         ud = elms[-1][-1]
!         elms[-1] = elms[-1][:-1]
!         elms = map(string.atoi, elms)
!         coords = 0.0
!         elen = len(elms)
!         if elen > 2:
!             coords = coords + float(elms[2])/3600.0
  
!         if elen > 1:
!             coords = coords + float(elms[1])/60.0
  
!         coords = coords + float(elms[0])
! 
!         if ud in ('W','S'):
!             coords = -1.0*coords
! 
!         f,i = math.modf(coords)
! 
!         if elen > 2:
!             f = float(fpformat.sci(f,4))
!         elif elen > 1:
!             f = float(fpformat.sci(f,2))
!         else:
!             f = 0.0
! 
!         return f+i
! 
!     def ParseReport(self, MetarReport=None):
!         """Take report with raw info only and return it with in 
!         parsed values filled in. Note: This function edits the
!         WeatherReport object you supply!"""
!         if self.Report is None and MetarReport is None:
!             raise EmptyReportException, \
!                 "No report given on init and ParseReport()."
!         elif MetarReport is not None:
!             self.Report=MetarReport
! 
!         lines=self.Report.fullreport.split("\n")
! 
!         #print "%s lines" % len(lines)
! 
!         for line in lines:
!             try:
!                 header, data=line.split(":",1)
!             except ValueError:
!                 header=data=line
! 
!             header=header.strip()
!             data=data.strip()
! 
!             #print header,'%%', data
! 
!             # The station id inside the report
!             if header.find("("+self.Report.givenstationid+")")!=-1:
                  try:
!                     loc,p=data.split("(",1)
!                     loc=loc.strip()
!                     rloc=self.strreverse(loc)
!                     rcoun,rcity=rloc.split(",",1)
                  except ValueError:
!                     city=""
!                     coun=""
!                     p=data
!                 try:
!                     id,lat,long,ht=p.split()
!                     ht=int(ht[:-1]) # cut off 'M' for meters
!                 except ValueError:
!                     id,lat,long=p.split()
!                     ht=None
!                 self.Report.stat_city=self.strreverse(rcity.strip())
!                 self.Report.stat_country=self.strreverse(rcoun.strip())
!                 self.Report.fulln=loc
!                 self.Report.latitude=lat
!                 self.Report.longitude=long
!                 self.Report.latf=self.parseLatLong(lat)
!                 self.Report.longf=self.parseLatLong(long)
!                 self.Report.altitude=ht
  
!             # The line containing date and timr of the report
  
!             elif (data.find("UTC"))!=-1:
!                 local,rt=data.split("/")
!                 self.Report.rtime=rt.strip()
! 
!             # temperature
! 
!             elif (header == "Temperature"):
!                 t,i=data.split(" ",1)
!                 self.Report.temp=(float(t)-32)*(5.0/9.0)
! 
!             # wind dir and speed
!             
!             elif (header == "Wind"):
!                 #print header
!                 if (data.find("Calm")!=-1):
!                     #print "calm"
!                     self.Report.windspeed=0.0
!                     self.Report.winddir=None
!                     self.Report.windcomp=None
!                 elif (data.find("Variable")!=-1):
!                     #print "var"
!                     v,a,speed,r=data.split(" ",3)
!                     self.Report.windspeed=(float(speed)*0.44704)
!                     self.Report.winddir=None
!                     self.Report.windcomp=None
!                 else:
!                     #print "elab"
!                     f,t,comp,deg,r,d,speed,r=data.split(" ",7)
!                     self.Report.winddir=int(deg[1:])
!                     self.Report.windcomp=comp.strip()
!                     self.Report.windspeed=(float(speed)*0.44704)
! 
!             # visibility
! 
!             elif (header == "Visibility"):
!                 for d in data.split():
                      try:
!                         self.Report.vis=float(d)*1.609344
!                         break
                      except ValueError:
!                         pass
  
!             # dew point
!             
!             elif (header == "Dew Point"):
!                 dp,i=data.split(" ",1)
!                 self.Report.dewp=(float(dp)-32)*(5.0/9.0)
  
!             # humidity
!              
!             elif (header == "Relative Humidity"):
!                 h,i=data.split("%",1)
!                 self.Report.humid=int(h)
  
!             # pressure
!             
!             elif (header == "Pressure (altimeter)"):
!                 p,r=data.split(" ",1)
!                 self.Report.press=(float(p)*33.863886)
  
!             # shot weather desc. ("rain", "mist", ...)
!             
!             elif (header == "Weather"):
!                 self.Report.weather=data
  
!             # short desc. of sky conditions
  
!             elif (header == "Sky conditions"):
!                 self.Report.sky=data
  
!             # the encoded report itself
!             
!             elif (header == "ob"):
!                 self.Report.code=data.strip()
  
!             # the cycle value ("time slot")
  
!             elif (header == "cycle"):
!                 self.Report.cycle=int(data)
  
!         # cloud info
!         cloudinfo = self.extractCloudInformation()
!         if cloudinfo is not None :
!             (cloudinfo, cloudpixmap) = cloudinfo
!         else :
!             (cloudinfo, cloudpixmap) = (None, None)
!         conditions = self.extractSkyConditions()
!         if conditions is not None :
!             (conditions, condpixmap) = conditions
!         else :
!             (conditions, condpixmap) = (None, None)
  
!         # fill the weather information
!         self.Report.weather = self.Report.weather or conditions or cloudinfo
  
!         # Pixmap guessed from general conditions has priority
!         # over pixmap guessed from clouds
!         self.Report.pixmap = condpixmap or cloudpixmap
  
!         # report is complete
!         self.Report.valid = 1
  
!         return self.Report
  
! class ReportFetcher:
!     """Fetches a report from a given METAR id, optionally taking into
!        account a different baseurl and using environment var-specified 
!        proxies."""
! 
!     def __init__(self, MetarStationCode=None, 
baseurl="http://weather.noaa.gov/pub/data/observations/metar/decoded/";):
!         """Set stationid attribute"""
!         self.stationid=MetarStationCode
!         self.baseurl=baseurl
! 
!     def FetchReport(self, StationCode=None):
!         """Fetch a report for a given station ID from the baseurl given
!         upon creation of the ReportFetcher instance."""
!         if self.stationid is None and StationCode is None:
!             raise EmptyIDException, \
!                 "No ID given on init and FetchReport()."
!         elif StationCode is not None:
!             self.stationid=StationCode
! 
!         self.stationid=self.stationid.upper()
!         self.reporturl="%s%s.TXT" % (self.baseurl, self.stationid)
!         urllib2.install_opener(
!             urllib2.build_opener(urllib2.ProxyHandler, urllib2.HTTPHandler))
!         try:
!             fn=urllib2.urlopen(self.reporturl)
!         except urllib2.HTTPError, why:
!             raise NetworkException, why
! 
!         # Dump entire report in a variable
!         self.fullreport=fn.read()
! 
!         if fn.info().status:
!             raise NetworkException, "Could not fetch METAR report"
!             
!         report=WeatherReport(self.stationid)
!         report.reporturl=self.reporturl
!         report.fullreport=self.fullreport
! 
!         return report
!         
  




-------------------------------------------------------
This SF.net email is sponsored by: SF.net Giveback Program.
Does SourceForge.net help you be more productive?  Does it
help you create better code?  SHARE THE LOVE, and help us help
YOU!  Click Here: http://sourceforge.net/donate/
_______________________________________________
Freevo-cvslog mailing list
[EMAIL PROTECTED]
https://lists.sourceforge.net/lists/listinfo/freevo-cvslog

Reply via email to