avwx.current.base

Current report shared resources.

  1"""Current report shared resources."""
  2
  3# stdlib
  4from __future__ import annotations
  5
  6import asyncio as aio
  7from typing import TYPE_CHECKING
  8
  9# module
 10from avwx.base import ManagedReport
 11from avwx.service import get_service
 12from avwx.static.core import WX_TRANSLATIONS
 13from avwx.structs import Code, Coord, ReportData, ReportTrans, Sanitization, Units
 14
 15if TYPE_CHECKING:
 16    from datetime import date
 17
 18
 19def wx_code(code: str) -> Code | str:
 20    """Translate weather codes into readable strings.
 21
 22    Returns translated string of variable length
 23    """
 24    if not code:
 25        return ""
 26    ret, code_copy = "", code
 27    if code[0] == "+":
 28        ret = "Heavy "
 29        code = code[1:]
 30    elif code[0] == "-":
 31        ret = "Light "
 32        code = code[1:]
 33    # Return code if code is not a code, ex R03/03002V03
 34    if len(code) not in [2, 4, 6] or code.isdigit():
 35        return code
 36    is_code = False
 37    while code:
 38        try:
 39            ret += f"{WX_TRANSLATIONS[code[:2]]} "
 40            is_code = True
 41        except KeyError:
 42            ret += code[:2]
 43        code = code[2:]
 44    # Return Code if any part was able to be translated
 45    return Code(code_copy, ret.strip()) if is_code else code_copy
 46
 47
 48def get_wx_codes(codes: list[str]) -> tuple[list[str], list[Code]]:
 49    """Separate parsed WX codes."""
 50    other: list[str] = []
 51    ret: list[Code] = []
 52    for item in codes:
 53        code = wx_code(item)
 54        if isinstance(code, Code):
 55            ret.append(code)
 56        else:
 57            other.append(code)
 58    return other, ret
 59
 60
 61class Report(ManagedReport):
 62    """Base report to take care of service assignment and station info."""
 63
 64    #: ReportTrans dataclass of translation strings from data. Parsed on update()
 65    translations: ReportTrans | None = None
 66
 67    sanitization: Sanitization | None = None
 68
 69    def __init__(self, code: str):
 70        """Add doc string to show constructor."""
 71        super().__init__(code)
 72        if self.station is not None:
 73            service = get_service(code, self.station.country)
 74            self.service = service(self.__class__.__name__.lower())  # type: ignore
 75
 76
 77class Reports(ManagedReport):
 78    """Base class containing multiple reports."""
 79
 80    coord: Coord | None = None
 81    raw: list[str] | None = None  # type: ignore
 82    data: list[ReportData] | None = None  # type: ignore
 83    units: Units = Units.north_american()
 84    sanitization: list[Sanitization] | None = None
 85
 86    def __init__(self, code: str | None = None, coord: Coord | None = None):
 87        if code:
 88            super().__init__(code)
 89            if self.station is not None:
 90                coord = self.station.coord
 91        elif coord is None:
 92            msg = "No station or coordinate given"
 93            raise ValueError(msg)
 94        self.coord = coord
 95
 96    def __repr__(self) -> str:
 97        if self.code:
 98            return f"<avwx.{self.__class__.__name__} code={self.code}>"
 99        return f"<avwx.{self.__class__.__name__} coord={self.coord}>"
100
101    @staticmethod
102    def _report_filter(reports: list[str]) -> list[str]:
103        """Apply any report filtering before updating raw_reports."""
104        return reports
105
106    async def _update(  # type: ignore
107        self, reports: list[str], issued: date | None, *, disable_post: bool
108    ) -> bool:
109        if not reports:
110            return False
111        reports = self._report_filter(reports)
112        return await super()._update(reports, issued, disable_post=disable_post)
113
114    def parse(self, reports: str | list[str], issued: date | None = None) -> bool:
115        """Update report data by parsing a given report.
116
117        Can accept a report issue date if not a recent report string
118        """
119        return aio.run(self.async_parse(reports, issued))
120
121    async def async_parse(self, reports: str | list[str], issued: date | None = None) -> bool:
122        """Async update report data by parsing a given report.
123
124        Can accept a report issue date if not a recent report string
125        """
126        self.source = None
127        if isinstance(reports, str):
128            reports = [reports]
129        return await self._update(reports, issued, disable_post=False)
130
131    def update(self, timeout: int = 10, *, disable_post: bool = False) -> bool:
132        """Update report data by fetching and parsing the report.
133
134        Returns True if new reports are available, else False
135        """
136        return aio.run(self.async_update(timeout, disable_post=disable_post))
137
138    async def async_update(self, timeout: int = 10, *, disable_post: bool = False) -> bool:
139        """Async update report data by fetching and parsing the report."""
140        reports = await self.service.async_fetch(coord=self.coord, timeout=timeout)  # type: ignore
141        self.source = self.service.root
142        return await self._update(reports, None, disable_post=disable_post)
def wx_code(code: str) -> avwx.structs.Code | str:
20def wx_code(code: str) -> Code | str:
21    """Translate weather codes into readable strings.
22
23    Returns translated string of variable length
24    """
25    if not code:
26        return ""
27    ret, code_copy = "", code
28    if code[0] == "+":
29        ret = "Heavy "
30        code = code[1:]
31    elif code[0] == "-":
32        ret = "Light "
33        code = code[1:]
34    # Return code if code is not a code, ex R03/03002V03
35    if len(code) not in [2, 4, 6] or code.isdigit():
36        return code
37    is_code = False
38    while code:
39        try:
40            ret += f"{WX_TRANSLATIONS[code[:2]]} "
41            is_code = True
42        except KeyError:
43            ret += code[:2]
44        code = code[2:]
45    # Return Code if any part was able to be translated
46    return Code(code_copy, ret.strip()) if is_code else code_copy

Translate weather codes into readable strings.

Returns translated string of variable length

def get_wx_codes(codes: list[str]) -> tuple[list[str], list[avwx.structs.Code]]:
49def get_wx_codes(codes: list[str]) -> tuple[list[str], list[Code]]:
50    """Separate parsed WX codes."""
51    other: list[str] = []
52    ret: list[Code] = []
53    for item in codes:
54        code = wx_code(item)
55        if isinstance(code, Code):
56            ret.append(code)
57        else:
58            other.append(code)
59    return other, ret

Separate parsed WX codes.

class Report(avwx.base.ManagedReport):
62class Report(ManagedReport):
63    """Base report to take care of service assignment and station info."""
64
65    #: ReportTrans dataclass of translation strings from data. Parsed on update()
66    translations: ReportTrans | None = None
67
68    sanitization: Sanitization | None = None
69
70    def __init__(self, code: str):
71        """Add doc string to show constructor."""
72        super().__init__(code)
73        if self.station is not None:
74            service = get_service(code, self.station.country)
75            self.service = service(self.__class__.__name__.lower())  # type: ignore

Base report to take care of service assignment and station info.

Report(code: str)
70    def __init__(self, code: str):
71        """Add doc string to show constructor."""
72        super().__init__(code)
73        if self.station is not None:
74            service = get_service(code, self.station.country)
75            self.service = service(self.__class__.__name__.lower())  # type: ignore

Add doc string to show constructor.

translations: avwx.structs.ReportTrans | None = None
sanitization: avwx.structs.Sanitization | None = None
class Reports(avwx.base.ManagedReport):
 78class Reports(ManagedReport):
 79    """Base class containing multiple reports."""
 80
 81    coord: Coord | None = None
 82    raw: list[str] | None = None  # type: ignore
 83    data: list[ReportData] | None = None  # type: ignore
 84    units: Units = Units.north_american()
 85    sanitization: list[Sanitization] | None = None
 86
 87    def __init__(self, code: str | None = None, coord: Coord | None = None):
 88        if code:
 89            super().__init__(code)
 90            if self.station is not None:
 91                coord = self.station.coord
 92        elif coord is None:
 93            msg = "No station or coordinate given"
 94            raise ValueError(msg)
 95        self.coord = coord
 96
 97    def __repr__(self) -> str:
 98        if self.code:
 99            return f"<avwx.{self.__class__.__name__} code={self.code}>"
100        return f"<avwx.{self.__class__.__name__} coord={self.coord}>"
101
102    @staticmethod
103    def _report_filter(reports: list[str]) -> list[str]:
104        """Apply any report filtering before updating raw_reports."""
105        return reports
106
107    async def _update(  # type: ignore
108        self, reports: list[str], issued: date | None, *, disable_post: bool
109    ) -> bool:
110        if not reports:
111            return False
112        reports = self._report_filter(reports)
113        return await super()._update(reports, issued, disable_post=disable_post)
114
115    def parse(self, reports: str | list[str], issued: date | None = None) -> bool:
116        """Update report data by parsing a given report.
117
118        Can accept a report issue date if not a recent report string
119        """
120        return aio.run(self.async_parse(reports, issued))
121
122    async def async_parse(self, reports: str | list[str], issued: date | None = None) -> bool:
123        """Async update report data by parsing a given report.
124
125        Can accept a report issue date if not a recent report string
126        """
127        self.source = None
128        if isinstance(reports, str):
129            reports = [reports]
130        return await self._update(reports, issued, disable_post=False)
131
132    def update(self, timeout: int = 10, *, disable_post: bool = False) -> bool:
133        """Update report data by fetching and parsing the report.
134
135        Returns True if new reports are available, else False
136        """
137        return aio.run(self.async_update(timeout, disable_post=disable_post))
138
139    async def async_update(self, timeout: int = 10, *, disable_post: bool = False) -> bool:
140        """Async update report data by fetching and parsing the report."""
141        reports = await self.service.async_fetch(coord=self.coord, timeout=timeout)  # type: ignore
142        self.source = self.service.root
143        return await self._update(reports, None, disable_post=disable_post)

Base class containing multiple reports.

coord: avwx.structs.Coord | None = None
raw: list[str] | None = None
data: list[avwx.structs.ReportData] | None = None
units: avwx.structs.Units = Units(accumulation='in', altimeter='inHg', altitude='ft', temperature='C', visibility='sm', wind_speed='kt')
sanitization: list[avwx.structs.Sanitization] | None = None
def parse( self, reports: str | list[str], issued: datetime.date | None = None) -> bool:
115    def parse(self, reports: str | list[str], issued: date | None = None) -> bool:
116        """Update report data by parsing a given report.
117
118        Can accept a report issue date if not a recent report string
119        """
120        return aio.run(self.async_parse(reports, issued))

Update report data by parsing a given report.

Can accept a report issue date if not a recent report string

async def async_parse( self, reports: str | list[str], issued: datetime.date | None = None) -> bool:
122    async def async_parse(self, reports: str | list[str], issued: date | None = None) -> bool:
123        """Async update report data by parsing a given report.
124
125        Can accept a report issue date if not a recent report string
126        """
127        self.source = None
128        if isinstance(reports, str):
129            reports = [reports]
130        return await self._update(reports, issued, disable_post=False)

Async update report data by parsing a given report.

Can accept a report issue date if not a recent report string

def update(self, timeout: int = 10, *, disable_post: bool = False) -> bool:
132    def update(self, timeout: int = 10, *, disable_post: bool = False) -> bool:
133        """Update report data by fetching and parsing the report.
134
135        Returns True if new reports are available, else False
136        """
137        return aio.run(self.async_update(timeout, disable_post=disable_post))

Update report data by fetching and parsing the report.

Returns True if new reports are available, else False

async def async_update(self, timeout: int = 10, *, disable_post: bool = False) -> bool:
139    async def async_update(self, timeout: int = 10, *, disable_post: bool = False) -> bool:
140        """Async update report data by fetching and parsing the report."""
141        reports = await self.service.async_fetch(coord=self.coord, timeout=timeout)  # type: ignore
142        self.source = self.service.root
143        return await self._update(reports, None, disable_post=disable_post)

Async update report data by fetching and parsing the report.