none-shall-parse 0.6.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- none_shall_parse/__init__.py +139 -0
- none_shall_parse/dates.py +801 -0
- none_shall_parse/imeis.py +211 -0
- none_shall_parse/lists.py +48 -0
- none_shall_parse/parse.py +196 -0
- none_shall_parse/strings.py +267 -0
- none_shall_parse/types.py +41 -0
- none_shall_parse-0.6.2.dist-info/METADATA +66 -0
- none_shall_parse-0.6.2.dist-info/RECORD +10 -0
- none_shall_parse-0.6.2.dist-info/WHEEL +4 -0
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
|
|
2
|
+
LUHN_DOUBLES = [0, 2, 4, 6, 8, 1, 3, 5, 7, 9]
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def get_luhn_digit(n: str | int) -> int:
|
|
6
|
+
"""
|
|
7
|
+
Calculates the Luhn checksum digit for a given number.
|
|
8
|
+
|
|
9
|
+
The function processes a number using the Luhn algorithm. It computes
|
|
10
|
+
the Luhn checksum digit based on the provided digits, ensuring that the
|
|
11
|
+
resulting number adheres to the Luhn standard. The method is useful for
|
|
12
|
+
validating numerical identifiers like credit card numbers or IMEIs.
|
|
13
|
+
|
|
14
|
+
Parameters:
|
|
15
|
+
n (str | int): A number represented as a string or integer that
|
|
16
|
+
requires Luhn checksum digit calculation.
|
|
17
|
+
|
|
18
|
+
Returns:
|
|
19
|
+
int: The Luhn checksum digit as an integer.
|
|
20
|
+
"""
|
|
21
|
+
chars = [int(ch) for ch in str(n)]
|
|
22
|
+
firsts = [ch for ch in chars[0::2]]
|
|
23
|
+
doubles = [LUHN_DOUBLES[ch] for ch in chars[1::2]]
|
|
24
|
+
check = 10 - divmod(sum((sum(firsts), sum(doubles))), 10)[1]
|
|
25
|
+
return divmod(check, 10)[1]
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def is_valid_luhn(n: str | int) -> bool:
|
|
29
|
+
"""
|
|
30
|
+
Determines if a given number, represented as a string or integer, adheres
|
|
31
|
+
to the Luhn algorithm.
|
|
32
|
+
|
|
33
|
+
The Luhn algorithm, also known as the mod 10 algorithm, is a simple checksum
|
|
34
|
+
formula used to validate identification numbers such as credit card numbers.
|
|
35
|
+
|
|
36
|
+
Parameters:
|
|
37
|
+
n : Union[str, int]
|
|
38
|
+
The input number to be validated. It can be provided as a string or an integer.
|
|
39
|
+
|
|
40
|
+
Returns:
|
|
41
|
+
bool
|
|
42
|
+
Returns True if the input number satisfies the Luhn algorithm; otherwise, False.
|
|
43
|
+
"""
|
|
44
|
+
n = "".join(
|
|
45
|
+
[
|
|
46
|
+
e
|
|
47
|
+
for e in n
|
|
48
|
+
if e
|
|
49
|
+
in [
|
|
50
|
+
0,
|
|
51
|
+
1,
|
|
52
|
+
2,
|
|
53
|
+
3,
|
|
54
|
+
4,
|
|
55
|
+
5,
|
|
56
|
+
6,
|
|
57
|
+
7,
|
|
58
|
+
8,
|
|
59
|
+
9,
|
|
60
|
+
"0",
|
|
61
|
+
"1",
|
|
62
|
+
"2",
|
|
63
|
+
"3",
|
|
64
|
+
"4",
|
|
65
|
+
"5",
|
|
66
|
+
"6",
|
|
67
|
+
"7",
|
|
68
|
+
"8",
|
|
69
|
+
"9",
|
|
70
|
+
]
|
|
71
|
+
]
|
|
72
|
+
)
|
|
73
|
+
chars = [int(ch) for ch in str(n)][::-1] # Reversed Digits
|
|
74
|
+
firsts = [ch for ch in chars[0::2]]
|
|
75
|
+
doubles = [LUHN_DOUBLES[ch] for ch in chars[1::2]]
|
|
76
|
+
final = sum((sum(firsts), sum(doubles)))
|
|
77
|
+
return divmod(final, 10)[1] == 0
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def is_valid_imei(n: str | int) -> bool:
|
|
81
|
+
"""
|
|
82
|
+
Determines whether the given number is a valid IMEI (International Mobile
|
|
83
|
+
Equipment Identity) number.
|
|
84
|
+
|
|
85
|
+
An IMEI number is a 15-digit unique identifier for a mobile device. This function
|
|
86
|
+
first checks that the length of the input is 15 characters and then validates
|
|
87
|
+
it using the Luhn algorithm.
|
|
88
|
+
|
|
89
|
+
Parameters:
|
|
90
|
+
n: Union[str, int]
|
|
91
|
+
The number to be checked, represented as a string or integer.
|
|
92
|
+
|
|
93
|
+
Returns:
|
|
94
|
+
bool
|
|
95
|
+
True if the given number is a valid IMEI, otherwise False.
|
|
96
|
+
"""
|
|
97
|
+
return len(str(n)) == 15 and is_valid_luhn(n)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def normalize_imei(c: str | int) -> str:
|
|
101
|
+
"""
|
|
102
|
+
Normalizes the given IMEI number by extracting the first 14 digits and appending
|
|
103
|
+
the calculated Luhn check digit to make it a valid IMEI.
|
|
104
|
+
|
|
105
|
+
The IMEI (International Mobile Equipment Identity) is a unique identifier
|
|
106
|
+
typically consisting of 15 digits. This function ensures that the provided
|
|
107
|
+
IMEI-like input is converted into a valid IMEI format by calculating and appending
|
|
108
|
+
the appropriate check digit.
|
|
109
|
+
|
|
110
|
+
Parameters:
|
|
111
|
+
c: Union[str, int]
|
|
112
|
+
The input IMEI or a value resembling an IMEI. It can be provided as a string
|
|
113
|
+
or an integer.
|
|
114
|
+
|
|
115
|
+
Returns:
|
|
116
|
+
str
|
|
117
|
+
A 15-digit valid IMEI as a string.
|
|
118
|
+
|
|
119
|
+
Raises:
|
|
120
|
+
Exception
|
|
121
|
+
Raises any exceptions occurring internally within the `get_luhn_digit` function
|
|
122
|
+
if the calculation of the check digit fails.
|
|
123
|
+
|
|
124
|
+
Notes:
|
|
125
|
+
This function assumes the presence of the `get_luhn_digit` function for Luhn
|
|
126
|
+
digit calculation.
|
|
127
|
+
"""
|
|
128
|
+
t = str(c)[:14]
|
|
129
|
+
check_digit = get_luhn_digit(t)
|
|
130
|
+
return "%s%s" % (t, check_digit)
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def get_tac_from_imei(n: str | int) -> tuple[bool, str]:
|
|
134
|
+
"""
|
|
135
|
+
Determines the validity of an IMEI number and extracts its TAC if valid.
|
|
136
|
+
|
|
137
|
+
This function checks whether a provided IMEI (International Mobile Equipment
|
|
138
|
+
Identity) number is valid based on IMEI validation rules. If the given IMEI
|
|
139
|
+
is valid, the function also extracts and returns the TAC (Type Allocation
|
|
140
|
+
Code), which corresponds to the first 8 digits of the IMEI.
|
|
141
|
+
|
|
142
|
+
Parameters:
|
|
143
|
+
n (str): The IMEI number to be validated and processed.
|
|
144
|
+
|
|
145
|
+
Returns:
|
|
146
|
+
tuple: A tuple containing a boolean indicating whether the IMEI is valid
|
|
147
|
+
and a string representing the TAC if valid or a placeholder if invalid.
|
|
148
|
+
"""
|
|
149
|
+
tac = "Not a Valid IMEI"
|
|
150
|
+
is_valid = is_valid_imei(n)
|
|
151
|
+
if not is_valid:
|
|
152
|
+
return False, tac
|
|
153
|
+
else:
|
|
154
|
+
tac = str(n)[:8]
|
|
155
|
+
return True, tac
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def decrement_imei(n: str | int) -> tuple[bool, str]:
|
|
159
|
+
"""
|
|
160
|
+
Decrements the given IMEI number by one and normalizes it.
|
|
161
|
+
|
|
162
|
+
This function validates the provided IMEI number. If it is a valid IMEI, the
|
|
163
|
+
function decrements the first 14 digits by one and computes the new IMEI
|
|
164
|
+
checksum to generate a normalized IMEI. If the provided IMEI is not valid,
|
|
165
|
+
it returns a failure status and an error message.
|
|
166
|
+
|
|
167
|
+
Parameters:
|
|
168
|
+
n: int
|
|
169
|
+
The IMEI number to be validated and decremented.
|
|
170
|
+
|
|
171
|
+
Returns:
|
|
172
|
+
tuple[bool, str]
|
|
173
|
+
A tuple where the first element is a boolean indicating whether the
|
|
174
|
+
operation was successful, and the second element is the resulting IMEI
|
|
175
|
+
or an error message if the input was invalid.
|
|
176
|
+
"""
|
|
177
|
+
result = "Not a Valid IMEI"
|
|
178
|
+
is_valid = is_valid_imei(n)
|
|
179
|
+
if not is_valid:
|
|
180
|
+
return False, result
|
|
181
|
+
else:
|
|
182
|
+
result = normalize_imei(int(str(n)[:14]) - 1)
|
|
183
|
+
return True, result
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
def increment_imei(n: str | int) -> tuple[bool, str]:
|
|
187
|
+
"""
|
|
188
|
+
Determines if a given IMEI number is valid and increments it by 1 if valid.
|
|
189
|
+
|
|
190
|
+
This function first checks if the provided IMEI number is valid using the
|
|
191
|
+
is_valid_imei function. If the input is a valid IMEI, it increments the IMEI
|
|
192
|
+
value by 1 while retaining only the first 14 digits. If the input is not valid,
|
|
193
|
+
it returns a predefined invalid result.
|
|
194
|
+
|
|
195
|
+
Parameters:
|
|
196
|
+
n: int
|
|
197
|
+
IMEI number to be validated and potentially incremented.
|
|
198
|
+
|
|
199
|
+
Returns:
|
|
200
|
+
tuple[bool, str]
|
|
201
|
+
A tuple where the first element is a boolean indicating whether the operation
|
|
202
|
+
was successful, and the second element is a string containing the incremented
|
|
203
|
+
IMEI number if valid or an error message if not valid.
|
|
204
|
+
"""
|
|
205
|
+
result = "Not a Valid IMEI"
|
|
206
|
+
is_valid = is_valid_imei(n)
|
|
207
|
+
if not is_valid:
|
|
208
|
+
return False, result
|
|
209
|
+
else:
|
|
210
|
+
result = normalize_imei(int(str(n)[:14]) + 1)
|
|
211
|
+
return True, result
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import collections
|
|
2
|
+
from typing import Iterable, Generator, Any, List
|
|
3
|
+
|
|
4
|
+
from .types import T
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def flatten(some_list: Iterable) -> Generator[Any, None, None]:
|
|
8
|
+
"""
|
|
9
|
+
Flattens a nested iterable into a one-dimensional generator.
|
|
10
|
+
|
|
11
|
+
This function takes an iterable, which may contain nested iterables,
|
|
12
|
+
and returns a generator that yields each element in a flattened order.
|
|
13
|
+
Strings and bytes are treated as atomic elements and will not be traversed
|
|
14
|
+
further as nested iterables.
|
|
15
|
+
|
|
16
|
+
:param some_list: A potentially nested iterable to be flattened.
|
|
17
|
+
:type some_list: Iterable
|
|
18
|
+
:return: A generator that yields elements from the input iterable in a
|
|
19
|
+
flattened order.
|
|
20
|
+
:rtype: Generator[Any, None, None]
|
|
21
|
+
"""
|
|
22
|
+
for el in some_list:
|
|
23
|
+
if isinstance(el, Iterable) and not isinstance(el, (str, bytes)):
|
|
24
|
+
yield from flatten(el)
|
|
25
|
+
else:
|
|
26
|
+
yield el
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def safe_list_get(lst: List[T], idx: int, default: T = None) -> T:
|
|
30
|
+
"""
|
|
31
|
+
Retrieve an element from a list by its index or return a default value if the index
|
|
32
|
+
is out of range or the input is not subscriptable. This function ensures safe retrieval
|
|
33
|
+
by providing a fallback value when access fails.
|
|
34
|
+
|
|
35
|
+
:param lst: The list from which the element is to be retrieved (may be None).
|
|
36
|
+
:type lst: List[T]
|
|
37
|
+
:param idx: The index of the element to retrieve from the list.
|
|
38
|
+
:type idx: int
|
|
39
|
+
:param default: The fallback value to be returned if retrieval fails.
|
|
40
|
+
:type default: T
|
|
41
|
+
:return: The element at the specified index, or the default value
|
|
42
|
+
if the index is out of range or lst is None/not subscriptable.
|
|
43
|
+
:rtype: T
|
|
44
|
+
"""
|
|
45
|
+
try:
|
|
46
|
+
return lst[idx]
|
|
47
|
+
except (IndexError, TypeError):
|
|
48
|
+
return default
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
from typing import Callable, Any
|
|
2
|
+
from typing import Union
|
|
3
|
+
|
|
4
|
+
from .strings import slugify
|
|
5
|
+
from .types import ChoicesType, StringLike
|
|
6
|
+
|
|
7
|
+
_true_set = {"yes", "true", "t", "y", "1"}
|
|
8
|
+
_false_set = {"no", "false", "f", "n", "0"}
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def str_to_bool(v: Any, raise_exc: bool = False) -> bool | None:
|
|
12
|
+
"""
|
|
13
|
+
Convert a string representation of a boolean into a boolean value.
|
|
14
|
+
|
|
15
|
+
This function takes a string input and attempts to interpret it as a boolean
|
|
16
|
+
value based on predefined sets of true and false representations. It can
|
|
17
|
+
also raise an exception for invalid inputs if specified.
|
|
18
|
+
|
|
19
|
+
:param v: The string value to be interpreted as boolean.
|
|
20
|
+
:type v: str
|
|
21
|
+
:param raise_exc: Determines whether to raise an exception for invalid inputs.
|
|
22
|
+
:type raise_exc: bool
|
|
23
|
+
:return: A boolean value interpreted from the input string or None if invalid.
|
|
24
|
+
:rtype: bool | None
|
|
25
|
+
:raises ValueError: If the input string is invalid and `raise_exc` is True.
|
|
26
|
+
"""
|
|
27
|
+
if isinstance(v, str):
|
|
28
|
+
v = v.lower()
|
|
29
|
+
if v in _true_set:
|
|
30
|
+
return True
|
|
31
|
+
if v in _false_set:
|
|
32
|
+
return False
|
|
33
|
+
|
|
34
|
+
if raise_exc:
|
|
35
|
+
raise ValueError('Expected "%s"' % '", "'.join(_true_set | _false_set))
|
|
36
|
+
return None
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def is_true(v: Any) -> bool:
|
|
40
|
+
"""
|
|
41
|
+
Determines whether the given value evaluates to a boolean `True`.
|
|
42
|
+
|
|
43
|
+
The function checks if the input value can be converted to a boolean
|
|
44
|
+
representation of `True` using the helper function `str_to_bool`.
|
|
45
|
+
|
|
46
|
+
:param v: The value to be evaluated for boolean truthiness
|
|
47
|
+
:type v: Any
|
|
48
|
+
:return: `True` if the value evaluates to boolean `True`, otherwise `False`
|
|
49
|
+
:rtype: bool
|
|
50
|
+
"""
|
|
51
|
+
return str_to_bool(v) is True
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def is_false(v: Any) -> bool:
|
|
55
|
+
"""
|
|
56
|
+
Determines if the given value evaluates to a boolean False.
|
|
57
|
+
|
|
58
|
+
This function utilizes the `str_to_bool` conversion to determine whether
|
|
59
|
+
the input value corresponds to a boolean `False`. It is particularly
|
|
60
|
+
useful for interpreting string-based representations of boolean values.
|
|
61
|
+
|
|
62
|
+
:param v: The value to be evaluated.
|
|
63
|
+
:type v: Any
|
|
64
|
+
:return: True if the value evaluates to False, otherwise False.
|
|
65
|
+
:rtype: bool
|
|
66
|
+
"""
|
|
67
|
+
return str_to_bool(v) is False
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def str_to_strs_list(s: str | None) -> list[str]:
|
|
71
|
+
"""
|
|
72
|
+
Parses a given string into an array of strings. The input string is split based on
|
|
73
|
+
commas or newline characters. Each resulting element is stripped of leading and
|
|
74
|
+
trailing whitespace, and empty items are excluded from the result. If the input
|
|
75
|
+
string is None, an empty list is returned.
|
|
76
|
+
|
|
77
|
+
:param s: The input string to be parsed. May be None.
|
|
78
|
+
:type s: str | None
|
|
79
|
+
:return: A list of non-empty, trimmed strings extracted from the input.
|
|
80
|
+
:rtype: list[str]
|
|
81
|
+
"""
|
|
82
|
+
return (
|
|
83
|
+
[]
|
|
84
|
+
if s is None
|
|
85
|
+
else [e.strip() for e in s.replace("\n", ",").split(",") if e.strip()]
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def int_to_bool(v: int | float) -> bool:
|
|
90
|
+
"""
|
|
91
|
+
Given an integer, convert it to bool.
|
|
92
|
+
If the integer is 1, return True, otherwise, return False.
|
|
93
|
+
|
|
94
|
+
Will raise an exception if the provided value cannot be cast to an integer.
|
|
95
|
+
:param v:
|
|
96
|
+
:exceptions: ValueError, TypeError
|
|
97
|
+
:return: True or False
|
|
98
|
+
"""
|
|
99
|
+
return int(v) == 1
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def int_or_none(s: int | float | str | None) -> int | None:
|
|
103
|
+
"""
|
|
104
|
+
Parses the input value and attempts to convert it into an integer. If the
|
|
105
|
+
input is invalid (such as being non-numeric), `None` is returned. If the
|
|
106
|
+
input is `-1` or `None`, it also returns `None`. Otherwise, the integer
|
|
107
|
+
value of the input is returned.
|
|
108
|
+
|
|
109
|
+
:param s: The input value to be parsed. Can be of type `int`, `float`, `str`,
|
|
110
|
+
or `None`.
|
|
111
|
+
:return: Returns the integer value of the input if successful. If the input
|
|
112
|
+
is invalid, equal to `-1`, or `None`, it returns `None`.
|
|
113
|
+
"""
|
|
114
|
+
if s is None:
|
|
115
|
+
return None
|
|
116
|
+
try:
|
|
117
|
+
if int(s) == -1:
|
|
118
|
+
return None
|
|
119
|
+
else:
|
|
120
|
+
return int(s)
|
|
121
|
+
except ValueError:
|
|
122
|
+
return None
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def choices_code_to_string(
|
|
126
|
+
choices: ChoicesType, default: str | None = None, to_slug: bool = False
|
|
127
|
+
) -> Callable[[Union[int, StringLike]], StringLike | None]:
|
|
128
|
+
"""
|
|
129
|
+
Converts a code to a corresponding string representation based on provided choices.
|
|
130
|
+
The function allows optional fallback to a default value and can slugify the resulting string
|
|
131
|
+
if required.
|
|
132
|
+
|
|
133
|
+
:param choices: A mapping of codes to string representations.
|
|
134
|
+
:type choices: ChoicesType
|
|
135
|
+
|
|
136
|
+
:param default: An optional default string to be returned if the code is not found in the choices.
|
|
137
|
+
:type default: str | None
|
|
138
|
+
|
|
139
|
+
:param to_slug: Specifies whether the resulting string should be slugified. If True, the string
|
|
140
|
+
representation is converted to a slug with hyphens replaced by underscores.
|
|
141
|
+
:type to_slug: bool
|
|
142
|
+
|
|
143
|
+
:return: A callable function that takes an input (code) and returns the corresponding string
|
|
144
|
+
representation or the default value. If to_slug is True, it returns the slugified version
|
|
145
|
+
instead.
|
|
146
|
+
:rtype: Callable[[Union[int, str]], str | None]
|
|
147
|
+
"""
|
|
148
|
+
dict_map = dict(choices)
|
|
149
|
+
|
|
150
|
+
def f(code):
|
|
151
|
+
return dict_map.get(code, default)
|
|
152
|
+
|
|
153
|
+
def s(code):
|
|
154
|
+
return slugify(dict_map.get(code, default)).replace("-", "_")
|
|
155
|
+
|
|
156
|
+
return s if to_slug else f
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
def choices_string_to_code(
|
|
160
|
+
choices: ChoicesType, default: Any = None, to_lower: bool = False
|
|
161
|
+
) -> Callable[[str], Union[int, str, None]]:
|
|
162
|
+
"""
|
|
163
|
+
Converts a dictionary of choices into a callable function that maps input strings
|
|
164
|
+
to their corresponding codes. This helper function is particularly useful for handling
|
|
165
|
+
mappings where string keys need to be converted into codes, while optionally allowing
|
|
166
|
+
the input to be case-insensitive.
|
|
167
|
+
|
|
168
|
+
:param choices: A dictionary-like object or sequence of tuples representing the choices.
|
|
169
|
+
:param default: Optional value returned if the input string does not match any key. Defaults to None.
|
|
170
|
+
:param to_lower: A boolean indicating whether to convert keys in the choice dictionary
|
|
171
|
+
and input string to lowercase for case-insensitive mapping. Defaults to False.
|
|
172
|
+
:return: A callable function that accepts a string input and returns the corresponding code from
|
|
173
|
+
the dictionary, or the default value if the input does not match.
|
|
174
|
+
"""
|
|
175
|
+
if to_lower:
|
|
176
|
+
dict_map = {v.lower(): k for k, v in dict(choices).items()}
|
|
177
|
+
else:
|
|
178
|
+
dict_map = {v: k for k, v in dict(choices).items()}
|
|
179
|
+
|
|
180
|
+
def f(word):
|
|
181
|
+
return dict_map.get(word, default)
|
|
182
|
+
|
|
183
|
+
return f
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
def none_or_empty(s=None):
|
|
187
|
+
"""
|
|
188
|
+
Check if the given thing is not empty and not None
|
|
189
|
+
:param s:
|
|
190
|
+
:return:
|
|
191
|
+
"""
|
|
192
|
+
if s is None:
|
|
193
|
+
return True
|
|
194
|
+
if s.strip() == "":
|
|
195
|
+
return True
|
|
196
|
+
return False
|