Ejemplo n.º 1
0
 def fetch(
     self,
     station: str = None,
     lat: float = None,
     lon: float = None,
     timeout: int = 10,
 ) -> str:
     """
     Fetches a report string from the service
     """
     if station:
         valid_station(station)
     elif lat is None or lon is None:
         raise ValueError("No valid fetch parameters")
     try:
         url, params = self._make_url(station, lat, lon)
         if self.method.lower() == "post":
             resp = requests.post(url,
                                  params=params,
                                  data=self._post_data(station))
         else:
             resp = requests.get(url, params)
         if resp.status_code != 200:
             raise SourceError(
                 f"{self.__class__.__name__} server returned {resp.status_code}"
             )
     except requests.exceptions.ConnectionError:
         raise ConnectionError(
             f"Unable to connect to {self.__class__.__name__} server")
     report = self._extract(resp.text, station)
     # This split join replaces all *whitespace elements with a single space
     if isinstance(report, list):
         return dedupe(" ".join(r.split()) for r in report)
     return " ".join(report.split())
Ejemplo n.º 2
0
 def __init__(self, icao: str):
     # Raises a BadStation error if needed
     station.valid_station(icao)
     self.station = icao
     self.station_info = Station.from_icao(icao)
     self.service = service.get_service(icao, self.station_info.country)(
         self.__class__.__name__.lower())
Ejemplo n.º 3
0
def parse(station: str, report: str, issued: date = None) -> Tuple[MetarData, Units]:
    """Returns MetarData and Units dataclasses with parsed data and their associated units"""
    valid_station(station)
    if not report:
        return None, None
    parser = parse_na if uses_na_format(station[:2]) else parse_in
    return parser(report, issued)
Ejemplo n.º 4
0
 def fetch(
     self,
     station: str = None,
     lat: float = None,
     lon: float = None,
     timeout: int = 10,
 ) -> str:
     """
     Fetches a report string from the service
     """
     if station:
         valid_station(station)
     elif lat is None or lon is None:
         raise ValueError("No valid fetch parameters")
     try:
         url, params = self._make_url(station, lat, lon)
         if self.method.lower() == "post":
             resp = httpx.post(url,
                               params=params,
                               data=self._post_data(station),
                               timeout=timeout)
         else:
             resp = httpx.get(url, params=params, timeout=timeout)
         if resp.status_code != 200:
             raise SourceError(
                 f"{self.__class__.__name__} server returned {resp.status_code}"
             )
     except (httpx.ConnectTimeout, httpx.ReadTimeout):
         raise TimeoutError(
             f"Timeout from {self.__class__.__name__} server")
     except gaierror:
         raise ConnectionError(
             f"Unable to connect to {self.__class__.__name__} server")
     report = self._extract(resp.text, station)
     return self._clean_report(report)
Ejemplo n.º 5
0
def parse(station: str, report: str) -> (MetarData, Units):
    """
    Returns MetarData and Units dataclasses with parsed data and their associated units
    """
    valid_station(station)
    if not report:
        return None, None
    return parse_na(report) if uses_na_format(station[:2]) else parse_in(report)
Ejemplo n.º 6
0
def parse(station: str, report: str) -> (TafData, Units):
    """
    Returns TafData and Units dataclasses with parsed data and their associated units
    """
    if not report:
        return None, None
    valid_station(station)
    while len(report) > 3 and report[:4] in ("TAF ", "AMD ", "COR "):
        report = report[4:]
    retwx = {
        "end_time": None,
        "raw": report,
        "remarks": None,
        "start_time": None
    }
    report = _core.sanitize_report_string(report)
    _, station, time = _core.get_station_and_time(report[:20].split())
    retwx["station"] = station
    retwx["time"] = _core.make_timestamp(time)
    report = report.replace(station, "")
    if time:
        report = report.replace(time, "").strip()
    if 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
Ejemplo n.º 7
0
    async def async_fetch(self,
                          station: str,
                          wait: bool = True,
                          timeout: int = 10,
                          force: bool = False) -> Optional[str]:
        """Asynchronously fetch a report string from the source file

        If wait, this will block if the file is already being updated

        Can force the service to fetch a new file
        """
        valid_station(station)
        if wait and self._updating:
            self._wait_until_updated()
        if force or self.is_outdated:
            if not await self.update(wait, timeout):
                return None
        with self._file.open() as fin:
            report = self._extract(station, fin)
        return report
Ejemplo n.º 8
0
 def __init__(self, station_ident: str):
     # Raises a BadStation error if needed
     station.valid_station(station_ident)
     self.service = service.get_service(station_ident)(
         self.__class__.__name__.lower())
     self.station = station_ident
Ejemplo n.º 9
0
 def __init__(self, icao: str):
     # Raises a BadStation error if needed
     valid_station(icao)
     self.icao = icao
     self.station = Station.from_icao(icao)