Repository: python-metar/python-metar

Issue:
Feet vs. Meters
This METAR has R28L/2600FT but reduction reads:

visual range: on runway 28L, 2600 meters
(should read: visual range: on runway 28L, 2600 feet)

Reference: METAR KPIT 091955Z COR 22015G25KT 3/4SM R28L/2600FT TSRA OVC010CB 18/16 A2992 RMK SLP045 T01820159

Discussion:

Patch:
diff --git a/metar/Metar.py b/metar/Metar.py
index 0e773cb..338e172 100755
--- a/metar/Metar.py
+++ b/metar/Metar.py
@@ -587,7 +587,7 @@ class Metar(object):
               self.vis_dir = direction(vis_dir)
           self.vis = distance(vis_dist, vis_units, vis_less)
                           
-  def _handleRunway( self, d ):
+  def _handleRunway(self, d):
       """
       Parse a runway visual range group.
       
@@ -596,15 +596,17 @@ class Metar(object):
           . name  [string]
           . low   [distance]
           . high  [distance]
-      """
-      if d['name']:
-          name = d['name']
-          low = distance(d['low'])
-          if d['high']:
-              high = distance(d['high'])
-          else:
-              high = low
-          self.runway.append((name,low,high))
+          . unit  [string]
+      """
+      if d['name'] is None:
+          return
+      unit = d['unit'] if d['unit'] is not None else 'FT'
+      low = distance(d['low'], unit)
+      if d['high'] is None:
+          high = low
+      else:
+          high = distance(d['high'], unit)
+      self.runway.append([d['name'], low, high, unit])
                           
   def _handleWeather( self, d ):
       """
@@ -1119,16 +1121,23 @@ class Metar(object):
               text += "; %s" % self.max_vis.string(units)
       return text
   
-  def runway_visual_range( self, units=None ):
+  def runway_visual_range(self, units=None):
       """
       Return a textual description of the runway visual range.
       """
       lines = []
-      for name,low,high in self.runway:
+      for name, low, high, unit in self.runway:
+          reportunits = unit if units is None else units
           if low != high:
-              lines.append("on runway %s, from %d to %s" % (name, low.value(units), high.string(units)))
+              lines.append(
+                  ("on runway %s, from %d to %s"
+                   ) % (name, low.value(reportunits),
+                        high.string(reportunits))
+              )
           else:
-              lines.append("on runway %s, %s" % (name, low.string(units)))
+              lines.append(
+                  "on runway %s, %s" % (name, low.string(reportunits))
+              )
       return "; ".join(lines)
   
   def present_weather( self ):


Test patch:
diff --git a/test/test_metar.py b/test/test_metar.py
index 76147e1..e6c8fee 100644
--- a/test/test_metar.py
+++ b/test/test_metar.py
@@ -17,6 +17,17 @@ class MetarTest(unittest.TestCase):
   def raisesParserError(self, code):
     self.assertRaises(Metar.ParserError, Metar.Metar, code )
 
+  def test_issue40_runwayunits(self):
+    """Check reported units on runway visual range."""
+    report = Metar.Metar(
+      "METAR KPIT 091955Z COR 22015G25KT 3/4SM R28L/2600FT TSRA OVC010CB "
+      "18/16 A2992 RMK SLP045 T01820159"
+    )
+    res = report.runway_visual_range()
+    self.assertEquals(res, 'on runway 28L, 2600 feet')
+    res = report.runway_visual_range('M')
+    self.assertTrue(res, 'on runway 28L, 792 meters')
+
   def test_010_parseType_default(self):
     """Check default value of the report type."""
     self.assertEqual( Metar.Metar("KEWR").type, "METAR" )