Example #1
0
 def test_uses_na_format(self):
     """
     METAR and TAF reports come in two flavors: North American and International
     
     uses_na_format should determine the format based on the station ident using prefixes
     """
     # NA stations
     for station in ('KJFK', 'PHNL', 'TNCM', 'MYNN'):
         self.assertTrue(core.uses_na_format(station))
     # IN stations
     for station in ('EGLL', 'MNAH', 'MUHA'):
         self.assertFalse(core.uses_na_format(station))
     # Bad stations
     for station in ('12K', 'MAYT'):
         with self.assertRaises(exceptions.BadStation):
             core.uses_na_format(station)
Example #2
0
 def test_uses_na_format(self):
     """
     METAR and TAF reports come in two flavors: North American and International
     
     uses_na_format should determine the format based on the station ident using prefixes
     """
     # NA stations
     for station in ('KJFK', 'PHNL', 'TNCM', 'MYNN'):
         self.assertTrue(core.uses_na_format(station))
     # IN stations
     for station in ('EGLL', 'MNAH', 'MUHA'):
         self.assertFalse(core.uses_na_format(station))
     # Bad stations
     for station in ('12K', 'MAYT'):
         with self.assertRaises(exceptions.BadStation):
             core.uses_na_format(station)
Example #3
0
def parse(station: str, report: str) -> (MetarData, Units):
    """
    Returns MetarData and Units dataclasses with parsed data and their associated units
    """
    core.valid_station(station)
    if not report:
        return None, None
    return parse_na(report) if core.uses_na_format(
        station[:2]) else parse_in(report)
Example #4
0
def parse(station: str, txt: str) -> {str: object}:
    """Returns a dictionary of parsed METAR data

    Keys: Station, Time, Wind-Direction, Wind-Speed, Wind-Gust, Wind-Variable-Dir,
          Visibility, Runway-Vis-List, Altimeter, Temperature, Dewpoint,
          Cloud-List, Other-List, Remarks, Units

    Units is dict of identified units of measurement for each field
    """
    core.valid_station(station)
    return parse_na(txt) if core.uses_na_format(station[:2]) else parse_in(txt)
Example #5
0
def parse(station: str, report: str) -> TafData:
    """
    Returns TafData and Units dataclasses with parsed data and their associated units
    """
    if not report:
        return None, None
    core.valid_station(station)
    while len(report) > 3 and report[:4] in ('TAF ', 'AMD ', 'COR '):
        report = report[4:]
    _, station, time = core.get_station_and_time(report[:20].split())
    retwx = {
        'end_time': None,
        'raw': report,
        'remarks': None,
        'start_time': None,
        'station': station,
        'time': core.make_timestamp(time)
    }
    report = report.replace(station, '')
    report = report.replace(time, '').strip()
    if core.uses_na_format(station):
        use_na = True
        units = Units(**NA_UNITS)
    else:
        use_na = False
        units = Units(**IN_UNITS)
    # Find and remove remarks
    report, retwx['remarks'] = core.get_taf_remarks(report)
    # Split and parse each line
    lines = core.split_taf(report)
    parsed_lines = parse_lines(lines, units, use_na)
    # Perform additional info extract and corrections
    if parsed_lines:
        parsed_lines[-1]['other'], retwx['max_temp'], retwx['min_temp'] \
            = core.get_temp_min_and_max(parsed_lines[-1]['other'])
        if not (retwx['max_temp'] or retwx['min_temp']):
            parsed_lines[0]['other'], retwx['max_temp'], retwx['min_temp'] \
                = core.get_temp_min_and_max(parsed_lines[0]['other'])
        # Set start and end times based on the first line
        start, end = parsed_lines[0]['start_time'], parsed_lines[0]['end_time']
        parsed_lines[0]['end_time'] = None
        retwx['start_time'], retwx['end_time'] = start, end
        parsed_lines = core.find_missing_taf_times(parsed_lines, start, end)
        parsed_lines = core.get_taf_flight_rules(parsed_lines)
    # Extract Oceania-specific data
    if retwx['station'][0] == 'A':
        parsed_lines[-1]['other'], retwx['alts'], retwx['temps'] \
            = core.get_oceania_temp_and_alt(parsed_lines[-1]['other'])
    # Convert to dataclass
    retwx['forecast'] = [TafLineData(**line) for line in parsed_lines]
    return TafData(**retwx), units
Example #6
0
def parse(station: str, report: str) -> TafData:
    """
    Returns TafData and Units dataclasses with parsed data and their associated units
    """
    if not report:
        return None, None
    core.valid_station(station)
    while len(report) > 3 and report[:4] in ('TAF ', 'AMD ', 'COR '):
        report = report[4:]
    _, station, time = core.get_station_and_time(report[:20].split())
    retwx = {
        'end_time': None,
        'raw': report,
        'remarks': None,
        'start_time': None,
        'station': station,
        'time': core.make_timestamp(time)
    }
    report = report.replace(station, '')
    report = report.replace(time, '').strip()
    if core.uses_na_format(station):
        use_na = True
        units = Units(**NA_UNITS)
    else:
        use_na = False
        units = Units(**IN_UNITS)
    # Find and remove remarks
    report, retwx['remarks'] = core.get_taf_remarks(report)
    # Split and parse each line
    lines = core.split_taf(report)
    parsed_lines = parse_lines(lines, units, use_na)
    # Perform additional info extract and corrections
    if parsed_lines:
        parsed_lines[-1]['other'], retwx['max_temp'], retwx['min_temp'] \
            = core.get_temp_min_and_max(parsed_lines[-1]['other'])
        if not (retwx['max_temp'] or retwx['min_temp']):
            parsed_lines[0]['other'], retwx['max_temp'], retwx['min_temp'] \
                = core.get_temp_min_and_max(parsed_lines[0]['other'])
        # Set start and end times based on the first line
        start, end = parsed_lines[0]['start_time'], parsed_lines[0]['end_time']
        parsed_lines[0]['end_time'] = None
        retwx['start_time'], retwx['end_time'] = start, end
        parsed_lines = core.find_missing_taf_times(parsed_lines, start, end)
        parsed_lines = core.get_taf_flight_rules(parsed_lines)
    # Extract Oceania-specific data
    if retwx['station'][0] == 'A':
        parsed_lines[-1]['other'], retwx['alts'], retwx['temps'] \
            = core.get_oceania_temp_and_alt(parsed_lines[-1]['other'])
    # Convert to dataclass
    retwx['forecast'] = [TafLineData(**line) for line in parsed_lines]
    return TafData(**retwx), units
Example #7
0
def parse(station: str, txt: str) -> (MetarData, Units):
    """
    Returns MetarData and Units dataclasses with parsed data and their associated units
    """
    core.valid_station(station)
    return parse_na(txt) if core.uses_na_format(station[:2]) else parse_in(txt)
Example #8
0
def parse(station: str,
          txt: str,
          delim: str = '<br/>&nbsp;&nbsp;') -> {
              str: object
          }:
    """
    Returns a dictionary of parsed TAF data

    'delim' is the divider between forecast lines. Ex: aviationweather.gov uses '<br/>&nbsp;&nbsp;'

    Keys: Station, Time, Forecast, Remarks, Min-Temp, Max-Temp, Units

    Oceania stations also have the following keys: Temp-List, Alt-List

    Forecast is list of report dicts in order of time with the following keys:
    Type, Start-Time, End-Time, Flight-Rules, Wind-Direction, Wind-Speed, Wind-Gust, Wind-Shear,
    Visibility, Altimeter, Cloud-List, Icing-List, Turb-List, Other-List, Probability, Raw-Line

    Units is dict of identified units of measurement for each field
    """
    core.valid_station(station)
    retwx = {}
    while len(txt) > 3 and txt[:4] in ['TAF ', 'AMD ', 'COR ']:
        txt = txt[4:]
    _, retwx['Station'], retwx['Time'] = core.get_station_and_time(
        txt[:20].split(' '))
    txt = txt.replace(retwx['Station'], '')
    txt = txt.replace(retwx['Time'], '')
    if core.uses_na_format(retwx['Station']):
        is_international = False
        units = copy(NA_UNITS)
    else:
        is_international = True
        units = copy(IN_UNITS)
    retwx['Remarks'] = ''
    parsed_lines = []
    prob = ''
    lines = txt.strip(' ').split(delim)
    while lines:
        line = lines[0].strip(' ')
        line = core.sanitize_line(line)
        #Remove Remarks from line
        index = core.find_first_in_list(line, TAF_RMK)
        if index != -1:
            retwx['Remarks'] = line[index:]
            line = line[:index].strip(' ')
        #Separate new lines fixed by sanitizeLine
        index = core.find_first_in_list(line, TAF_NEWLINE)
        if index != -1:
            lines.insert(1, line[index + 1:])
            line = line[:index]
        # Remove prob from the beginning of a line
        if line.startswith('PROB'):
            # Add standalone prob to next line
            if len(line) == 6:
                prob = line
                line = ''
            # Add to current line
            elif len(line) > 6:
                prob = line[:6]
                line = line[6:].strip()
        if line:
            # Separate full prob forecast into its own line
            if ' PROB' in line:
                probindex = line.index(' PROB')
                lines.insert(1, line[probindex + 1:])
                line = line[:probindex]
            raw_line = prob + ' ' + line if prob else line
            parsed_line, units = parse_in_line(line, units) if is_international \
                else parse_na_line(line, units)
            parsed_line['Probability'] = prob[4:]
            parsed_line['Raw-Line'] = raw_line
            prob = ''
            parsed_lines.append(parsed_line)
        lines.pop(0)
    if parsed_lines:
        parsed_lines[len(parsed_lines) - 1]['Other-List'], retwx['Max-Temp'], retwx['Min-Temp'] \
            = core.get_temp_min_and_max(parsed_lines[len(parsed_lines) - 1]['Other-List'])
        if not (retwx['Max-Temp'] or retwx['Min-Temp']):
            parsed_lines[0]['Other-List'], retwx['Max-Temp'], retwx['Min-Temp'] \
                = core.get_temp_min_and_max(parsed_lines[0]['Other-List'])
        parsed_lines = core.find_missing_taf_times(parsed_lines)
        parsed_lines = core.get_taf_flight_rules(parsed_lines)
    else:
        retwx['Min-Temp'] = ['', '']
        retwx['Max-Temp'] = ['', '']
    if retwx['Station'][0] == 'A':
        parsed_lines[len(parsed_lines) - 1]['Other-List'], retwx['Alt-List'], retwx['Temp-List'] \
            = core.get_oceania_temp_and_alt(parsed_lines[len(parsed_lines) - 1]['Other-List'])
    retwx['Forecast'] = parsed_lines
    retwx['Units'] = units
    return retwx