avwx.parsing.sanitization.cleaners.separated

Cleaners where an element is separated.

  1"""Cleaners where an element is separated."""
  2
  3from avwx.parsing.sanitization.base import CombineItems
  4from avwx.static.core import CLOUD_LIST, CLOUD_TRANSLATIONS, WIND_UNITS
  5
  6
  7class SeparatedDistance(CombineItems):
  8    """Distance digit and/or unit.
  9    Ex: 10 SM
 10    """
 11
 12    def can_handle(self, first: str, second: str) -> bool:
 13        return first.isdigit() and second in {"SM", "0SM"}
 14
 15
 16class SeparatedFirstTemperature(CombineItems):
 17    """Temperature before slash.
 18    Ex: 12 /10
 19    """
 20
 21    def can_handle(self, first: str, second: str) -> bool:
 22        return first.isdigit() and len(second) > 2 and second[0] == "/" and second[1:].isdigit()
 23
 24
 25class SeparatedCloudAltitude(CombineItems):
 26    """Known cloud types.
 27    Ex: OVC 040
 28    """
 29
 30    def can_handle(self, first: str, second: str) -> bool:
 31        return second.isdigit() and first in CLOUD_LIST
 32
 33
 34class SeparatedSecondTemperature(CombineItems):
 35    """Temperature after slash.
 36    Ex: 12/ 10
 37    """
 38
 39    def can_handle(self, first: str, second: str) -> bool:
 40        return second.isdigit() and len(first) > 2 and first.endswith("/") and first[:-1].isdigit()
 41
 42
 43class SeparatedAltimeterLetter(CombineItems):
 44    """Altimeter letter prefix.
 45    Ex: Q 1001
 46    """
 47
 48    def can_handle(self, first: str, second: str) -> bool:
 49        if not second.isdigit():
 50            return False
 51        if first == "Q":
 52            return second[0] in {"0", "1"}
 53        return second[0] in {"2", "3"} if first == "A" else False
 54
 55
 56class SeparatedTemperatureTrailingDigit(CombineItems):
 57    """Dewpoint split.
 58    Ex: 12/1 0
 59    """
 60
 61    def can_handle(self, first: str, second: str) -> bool:
 62        return (
 63            len(second) == 1
 64            and second.isdigit()
 65            and len(first) > 3
 66            and first[:2].isdigit()
 67            and "/" in first
 68            and first[3:].isdigit()
 69        )
 70
 71
 72class SeparatedWindUnit(CombineItems):
 73    """Wind unit disconnected or split in two."""
 74
 75    def can_handle(self, first: str, second: str) -> bool:
 76        # 36010G20 KT
 77        if (
 78            second in WIND_UNITS
 79            and first[-1].isdigit()
 80            and (first[:5].isdigit() or (first.startswith("VRB") and first[3:5].isdigit()))
 81        ):
 82            return True
 83        # 36010K T
 84        return (
 85            second == "T"
 86            and len(first) >= 6
 87            and (first[:5].isdigit() or (first.startswith("VRB") and first[3:5].isdigit()))
 88            and first[-1] == "K"
 89        )
 90
 91
 92class SeparatedCloudQualifier(CombineItems):
 93    """Cloud descriptors.
 94    Ex: OVC022 CB
 95    """
 96
 97    def can_handle(self, first: str, second: str) -> bool:
 98        return second in CLOUD_TRANSLATIONS and second not in CLOUD_LIST and len(first) >= 3 and first[:3] in CLOUD_LIST
 99
100
101class SeparatedTafTimePrefix(CombineItems):
102    """TAF new time period.
103    Ex: FM 122400
104    """
105
106    def can_handle(self, first: str, second: str) -> bool:
107        return first in {"FM", "TL"} and (second.isdigit() or (second.endswith("Z") and second[:-1].isdigit()))
108
109
110class SeparatedMinMaxTemperaturePrefix(CombineItems):
111    """TAF min max temperature prefix.
112    Ex: TX 20/10
113    """
114
115    def can_handle(self, first: str, second: str) -> bool:
116        return first in {"TX", "TN"} and "/" in second
class SeparatedDistance(avwx.parsing.sanitization.cleaners.base.CombineItems):
 8class SeparatedDistance(CombineItems):
 9    """Distance digit and/or unit.
10    Ex: 10 SM
11    """
12
13    def can_handle(self, first: str, second: str) -> bool:
14        return first.isdigit() and second in {"SM", "0SM"}

Distance digit and/or unit. Ex: 10 SM

def can_handle(self, first: str, second: str) -> bool:
13    def can_handle(self, first: str, second: str) -> bool:
14        return first.isdigit() and second in {"SM", "0SM"}

Return True if both elements can and need to be combined.

class SeparatedFirstTemperature(avwx.parsing.sanitization.cleaners.base.CombineItems):
17class SeparatedFirstTemperature(CombineItems):
18    """Temperature before slash.
19    Ex: 12 /10
20    """
21
22    def can_handle(self, first: str, second: str) -> bool:
23        return first.isdigit() and len(second) > 2 and second[0] == "/" and second[1:].isdigit()

Temperature before slash. Ex: 12 /10

def can_handle(self, first: str, second: str) -> bool:
22    def can_handle(self, first: str, second: str) -> bool:
23        return first.isdigit() and len(second) > 2 and second[0] == "/" and second[1:].isdigit()

Return True if both elements can and need to be combined.

class SeparatedCloudAltitude(avwx.parsing.sanitization.cleaners.base.CombineItems):
26class SeparatedCloudAltitude(CombineItems):
27    """Known cloud types.
28    Ex: OVC 040
29    """
30
31    def can_handle(self, first: str, second: str) -> bool:
32        return second.isdigit() and first in CLOUD_LIST

Known cloud types. Ex: OVC 040

def can_handle(self, first: str, second: str) -> bool:
31    def can_handle(self, first: str, second: str) -> bool:
32        return second.isdigit() and first in CLOUD_LIST

Return True if both elements can and need to be combined.

class SeparatedSecondTemperature(avwx.parsing.sanitization.cleaners.base.CombineItems):
35class SeparatedSecondTemperature(CombineItems):
36    """Temperature after slash.
37    Ex: 12/ 10
38    """
39
40    def can_handle(self, first: str, second: str) -> bool:
41        return second.isdigit() and len(first) > 2 and first.endswith("/") and first[:-1].isdigit()

Temperature after slash. Ex: 12/ 10

def can_handle(self, first: str, second: str) -> bool:
40    def can_handle(self, first: str, second: str) -> bool:
41        return second.isdigit() and len(first) > 2 and first.endswith("/") and first[:-1].isdigit()

Return True if both elements can and need to be combined.

class SeparatedAltimeterLetter(avwx.parsing.sanitization.cleaners.base.CombineItems):
44class SeparatedAltimeterLetter(CombineItems):
45    """Altimeter letter prefix.
46    Ex: Q 1001
47    """
48
49    def can_handle(self, first: str, second: str) -> bool:
50        if not second.isdigit():
51            return False
52        if first == "Q":
53            return second[0] in {"0", "1"}
54        return second[0] in {"2", "3"} if first == "A" else False

Altimeter letter prefix. Ex: Q 1001

def can_handle(self, first: str, second: str) -> bool:
49    def can_handle(self, first: str, second: str) -> bool:
50        if not second.isdigit():
51            return False
52        if first == "Q":
53            return second[0] in {"0", "1"}
54        return second[0] in {"2", "3"} if first == "A" else False

Return True if both elements can and need to be combined.

class SeparatedTemperatureTrailingDigit(avwx.parsing.sanitization.cleaners.base.CombineItems):
57class SeparatedTemperatureTrailingDigit(CombineItems):
58    """Dewpoint split.
59    Ex: 12/1 0
60    """
61
62    def can_handle(self, first: str, second: str) -> bool:
63        return (
64            len(second) == 1
65            and second.isdigit()
66            and len(first) > 3
67            and first[:2].isdigit()
68            and "/" in first
69            and first[3:].isdigit()
70        )

Dewpoint split. Ex: 12/1 0

def can_handle(self, first: str, second: str) -> bool:
62    def can_handle(self, first: str, second: str) -> bool:
63        return (
64            len(second) == 1
65            and second.isdigit()
66            and len(first) > 3
67            and first[:2].isdigit()
68            and "/" in first
69            and first[3:].isdigit()
70        )

Return True if both elements can and need to be combined.

class SeparatedWindUnit(avwx.parsing.sanitization.cleaners.base.CombineItems):
73class SeparatedWindUnit(CombineItems):
74    """Wind unit disconnected or split in two."""
75
76    def can_handle(self, first: str, second: str) -> bool:
77        # 36010G20 KT
78        if (
79            second in WIND_UNITS
80            and first[-1].isdigit()
81            and (first[:5].isdigit() or (first.startswith("VRB") and first[3:5].isdigit()))
82        ):
83            return True
84        # 36010K T
85        return (
86            second == "T"
87            and len(first) >= 6
88            and (first[:5].isdigit() or (first.startswith("VRB") and first[3:5].isdigit()))
89            and first[-1] == "K"
90        )

Wind unit disconnected or split in two.

def can_handle(self, first: str, second: str) -> bool:
76    def can_handle(self, first: str, second: str) -> bool:
77        # 36010G20 KT
78        if (
79            second in WIND_UNITS
80            and first[-1].isdigit()
81            and (first[:5].isdigit() or (first.startswith("VRB") and first[3:5].isdigit()))
82        ):
83            return True
84        # 36010K T
85        return (
86            second == "T"
87            and len(first) >= 6
88            and (first[:5].isdigit() or (first.startswith("VRB") and first[3:5].isdigit()))
89            and first[-1] == "K"
90        )

Return True if both elements can and need to be combined.

class SeparatedCloudQualifier(avwx.parsing.sanitization.cleaners.base.CombineItems):
93class SeparatedCloudQualifier(CombineItems):
94    """Cloud descriptors.
95    Ex: OVC022 CB
96    """
97
98    def can_handle(self, first: str, second: str) -> bool:
99        return second in CLOUD_TRANSLATIONS and second not in CLOUD_LIST and len(first) >= 3 and first[:3] in CLOUD_LIST

Cloud descriptors. Ex: OVC022 CB

def can_handle(self, first: str, second: str) -> bool:
98    def can_handle(self, first: str, second: str) -> bool:
99        return second in CLOUD_TRANSLATIONS and second not in CLOUD_LIST and len(first) >= 3 and first[:3] in CLOUD_LIST

Return True if both elements can and need to be combined.

class SeparatedTafTimePrefix(avwx.parsing.sanitization.cleaners.base.CombineItems):
102class SeparatedTafTimePrefix(CombineItems):
103    """TAF new time period.
104    Ex: FM 122400
105    """
106
107    def can_handle(self, first: str, second: str) -> bool:
108        return first in {"FM", "TL"} and (second.isdigit() or (second.endswith("Z") and second[:-1].isdigit()))

TAF new time period. Ex: FM 122400

def can_handle(self, first: str, second: str) -> bool:
107    def can_handle(self, first: str, second: str) -> bool:
108        return first in {"FM", "TL"} and (second.isdigit() or (second.endswith("Z") and second[:-1].isdigit()))

Return True if both elements can and need to be combined.

class SeparatedMinMaxTemperaturePrefix(avwx.parsing.sanitization.cleaners.base.CombineItems):
111class SeparatedMinMaxTemperaturePrefix(CombineItems):
112    """TAF min max temperature prefix.
113    Ex: TX 20/10
114    """
115
116    def can_handle(self, first: str, second: str) -> bool:
117        return first in {"TX", "TN"} and "/" in second

TAF min max temperature prefix. Ex: TX 20/10

def can_handle(self, first: str, second: str) -> bool:
116    def can_handle(self, first: str, second: str) -> bool:
117        return first in {"TX", "TN"} and "/" in second

Return True if both elements can and need to be combined.