os-normalizer 0.4.2__py3-none-any.whl → 0.5.0__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.
Potentially problematic release.
This version of os-normalizer might be problematic. Click here for more details.
- os_normalizer/constants.py +139 -2
- os_normalizer/cpe.py +57 -12
- os_normalizer/helpers.py +26 -15
- os_normalizer/models.py +19 -9
- os_normalizer/os_normalizer.py +76 -49
- os_normalizer/parsers/__init__.py +7 -3
- os_normalizer/parsers/bsd.py +2 -1
- os_normalizer/parsers/esxi.py +83 -0
- os_normalizer/parsers/linux.py +6 -5
- os_normalizer/parsers/macos.py +12 -14
- os_normalizer/parsers/mobile.py +23 -5
- os_normalizer/parsers/network/__init__.py +5 -1
- os_normalizer/parsers/network/cisco.py +13 -7
- os_normalizer/parsers/network/fortinet.py +15 -5
- os_normalizer/parsers/network/huawei.py +9 -3
- os_normalizer/parsers/network/juniper.py +10 -4
- os_normalizer/parsers/network/netgear.py +10 -3
- os_normalizer/parsers/solaris.py +100 -0
- os_normalizer/parsers/windows.py +39 -23
- {os_normalizer-0.4.2.dist-info → os_normalizer-0.5.0.dist-info}/METADATA +2 -1
- os_normalizer-0.5.0.dist-info/RECORD +24 -0
- os_normalizer-0.4.2.dist-info/RECORD +0 -22
- {os_normalizer-0.4.2.dist-info → os_normalizer-0.5.0.dist-info}/WHEEL +0 -0
- {os_normalizer-0.4.2.dist-info → os_normalizer-0.5.0.dist-info}/licenses/LICENSE +0 -0
os_normalizer/parsers/windows.py
CHANGED
|
@@ -12,6 +12,7 @@ from os_normalizer.constants import (
|
|
|
12
12
|
WINDOWS_NT_SERVER_MAP,
|
|
13
13
|
WINDOWS_PRODUCT_PATTERNS,
|
|
14
14
|
WINDOWS_SERVER_BUILD_MAP,
|
|
15
|
+
PrecisionLevel,
|
|
15
16
|
)
|
|
16
17
|
from os_normalizer.helpers import extract_arch_from_text, update_confidence
|
|
17
18
|
|
|
@@ -20,7 +21,8 @@ if TYPE_CHECKING:
|
|
|
20
21
|
|
|
21
22
|
VERSION_PATTERN = re.compile(r"\b(\d+)\.(\d+)\.(\d+)(?:\.(\d+))?\b")
|
|
22
23
|
NT_PATTERN = re.compile(r"\bnt\s*(\d+)(?:\.(\d+))?", re.IGNORECASE)
|
|
23
|
-
BUILD_PATTERN = re.compile(r"\bbuild\s*(?:number\s*)?(\d{3,5})\b", re.IGNORECASE)
|
|
24
|
+
BUILD_PATTERN = re.compile(r"\bbuild\s*(?:number\s*)?[:=\s-]*?(\d{3,5})\b", re.IGNORECASE)
|
|
25
|
+
KERNEL_PATTERN = re.compile(r"\bkernel\s*[:=\s-]*?(\d+)(?:\.(\d+))?", re.IGNORECASE)
|
|
24
26
|
SP_PATTERN = re.compile(r"\bsp(\d)\b", re.IGNORECASE)
|
|
25
27
|
|
|
26
28
|
EDITION_KEYWORDS: list[tuple[str, str]] = [
|
|
@@ -141,6 +143,13 @@ def _extract_version_state(text: str) -> VersionState:
|
|
|
141
143
|
state.nt_minor = state.nt_minor if state.nt_minor is not None else minr
|
|
142
144
|
state.explicit = True
|
|
143
145
|
|
|
146
|
+
if state.nt_major is None:
|
|
147
|
+
kernel_match = KERNEL_PATTERN.search(text)
|
|
148
|
+
if kernel_match:
|
|
149
|
+
state.nt_major = int(kernel_match.group(1))
|
|
150
|
+
state.nt_minor = int(kernel_match.group(2)) if kernel_match.group(2) else 0
|
|
151
|
+
state.explicit = True
|
|
152
|
+
|
|
144
153
|
if state.build is None:
|
|
145
154
|
build_match = BUILD_PATTERN.search(text)
|
|
146
155
|
if build_match:
|
|
@@ -157,11 +166,8 @@ def _apply_build_context(state: VersionState, product: str | None, server_hint:
|
|
|
157
166
|
return product, server_hint
|
|
158
167
|
|
|
159
168
|
product_from_build, channel, is_server_build = _lookup_build(build_num, server_hint)
|
|
160
|
-
if product_from_build:
|
|
161
|
-
|
|
162
|
-
product = product_from_build
|
|
163
|
-
elif product != product_from_build and _build_inference_is_more_precise(product, product_from_build):
|
|
164
|
-
product = product_from_build
|
|
169
|
+
if product_from_build and (not product or _build_inference_should_replace(product, product_from_build)):
|
|
170
|
+
product = product_from_build
|
|
165
171
|
if is_server_build:
|
|
166
172
|
server_hint = True
|
|
167
173
|
state.channel = channel
|
|
@@ -192,11 +198,18 @@ def _apply_version_numbers(p: OSData, defaults: ProductDefaults, state: VersionS
|
|
|
192
198
|
def _set_kernel_version(p: OSData, defaults: ProductDefaults | None, state: VersionState) -> None:
|
|
193
199
|
"""Populate kernel_version using explicit tokens, build channel, or defaults."""
|
|
194
200
|
kernel_version: str | None = None
|
|
195
|
-
if
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
201
|
+
if (
|
|
202
|
+
state.explicit
|
|
203
|
+
and state.channel
|
|
204
|
+
and (state.nt_major is None or state.nt_major >= 10)
|
|
205
|
+
and (defaults is None or defaults.kernel_version is None)
|
|
206
|
+
):
|
|
207
|
+
kernel_version = state.channel
|
|
208
|
+
elif state.explicit and state.nt_major is not None:
|
|
209
|
+
if state.nt_minor is not None:
|
|
199
210
|
kernel_version = f"{state.nt_major}.{state.nt_minor}"
|
|
211
|
+
elif state.nt_major >= 10 and state.channel:
|
|
212
|
+
kernel_version = state.channel
|
|
200
213
|
if kernel_version is None and defaults and defaults.kernel_version:
|
|
201
214
|
kernel_version = defaults.kernel_version
|
|
202
215
|
if kernel_version:
|
|
@@ -253,13 +266,16 @@ def _lookup_build(build_num: int, server_hint: bool) -> tuple[str | None, str |
|
|
|
253
266
|
return candidate
|
|
254
267
|
|
|
255
268
|
|
|
256
|
-
def
|
|
257
|
-
"""Return True when
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
269
|
+
def _build_inference_should_replace(existing: str, inferred: str) -> bool:
|
|
270
|
+
"""Return True when build metadata should override a detected product label."""
|
|
271
|
+
existing_lower = existing.lower()
|
|
272
|
+
inferred_lower = inferred.lower()
|
|
273
|
+
|
|
274
|
+
if existing_lower == inferred_lower:
|
|
275
|
+
return False
|
|
276
|
+
if inferred_lower.startswith(existing_lower):
|
|
277
|
+
return False
|
|
278
|
+
return True
|
|
263
279
|
|
|
264
280
|
|
|
265
281
|
def _product_from_nt(major: int, minor: int, server_hint: bool) -> str | None:
|
|
@@ -274,13 +290,13 @@ def _derive_precision(
|
|
|
274
290
|
minor: int | None,
|
|
275
291
|
patch: int | None,
|
|
276
292
|
build: str | None,
|
|
277
|
-
) ->
|
|
293
|
+
) -> PrecisionLevel:
|
|
278
294
|
if build:
|
|
279
|
-
return
|
|
295
|
+
return PrecisionLevel.BUILD
|
|
280
296
|
if patch is not None and patch != 0:
|
|
281
|
-
return
|
|
297
|
+
return PrecisionLevel.PATCH
|
|
282
298
|
if minor is not None:
|
|
283
|
-
return
|
|
299
|
+
return PrecisionLevel.MINOR
|
|
284
300
|
if major is not None:
|
|
285
|
-
return
|
|
286
|
-
return
|
|
301
|
+
return PrecisionLevel.MAJOR
|
|
302
|
+
return PrecisionLevel.PRODUCT
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: os-normalizer
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.5.0
|
|
4
4
|
Summary: Normalize raw OS strings/metadata into structured data (family, product, version, arch).
|
|
5
5
|
Project-URL: Homepage, https://github.com/johnscillieri/os-normalizer
|
|
6
6
|
Project-URL: Repository, https://github.com/johnscillieri/os-normalizer
|
|
@@ -38,6 +38,7 @@ Classifier: Programming Language :: Python :: 3 :: Only
|
|
|
38
38
|
Classifier: Programming Language :: Python :: 3.11
|
|
39
39
|
Classifier: Programming Language :: Python :: 3.12
|
|
40
40
|
Classifier: Programming Language :: Python :: 3.13
|
|
41
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
41
42
|
Classifier: Topic :: Software Development :: Libraries
|
|
42
43
|
Classifier: Topic :: System :: Operating System
|
|
43
44
|
Requires-Python: >=3.11
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
os_normalizer/__init__.py,sha256=ZA2JnO3juuAn8xQBqUoUXxca10B-rE1MIuwtzDofpKs,212
|
|
2
|
+
os_normalizer/constants.py,sha256=5qGUmZp7wYLjoyPng60ILEG14vDNq6DxywE2zsdHi6c,8550
|
|
3
|
+
os_normalizer/cpe.py,sha256=sf_fa7dCNUuGCKY_v2lEEUcKsZkh6NLavIGz0QjVD_o,11126
|
|
4
|
+
os_normalizer/helpers.py,sha256=sNKSiD0AhmEXwNsQtgTfT3L8TIwmv_KgLSP5h6p7NxI,3820
|
|
5
|
+
os_normalizer/models.py,sha256=c2uR9E5CVQUjdlXb0VIjwezEAY9fLuFyxA2oaOQ1YTw,6720
|
|
6
|
+
os_normalizer/os_normalizer.py,sha256=pTbNSQIfxI26vg73yOE8znG71ksd78RYzcGMvSi0z1s,11541
|
|
7
|
+
os_normalizer/parsers/__init__.py,sha256=UfknAu-0M7uQ8wMHBlhUcVVOtylBHCgyEenMiwatnRo,427
|
|
8
|
+
os_normalizer/parsers/bsd.py,sha256=krhrslh1nRAjeo_lg8_DhxygHUaUGV0srXUsNoWJVOg,2082
|
|
9
|
+
os_normalizer/parsers/esxi.py,sha256=tmDUk7Y45EQP9oqMaLsptMyq_G0z1Ki_Rgh_59W-4os,2694
|
|
10
|
+
os_normalizer/parsers/linux.py,sha256=jeRQcOAv-m7UuY6qiFKqbdPqLT8ywRCVBKq_TSFZCxs,3983
|
|
11
|
+
os_normalizer/parsers/macos.py,sha256=LeVS8OK9LgN8Y05KgfGOJdqOSgvfeFYNPc4MG3-gc-I,3728
|
|
12
|
+
os_normalizer/parsers/mobile.py,sha256=3D7rErCBMYiJtdZv-VPKhrc6Du236ch4yrnfuR1zWbs,1824
|
|
13
|
+
os_normalizer/parsers/solaris.py,sha256=mJjzk5chFKSy2NEHzq5xUPtk_123JJKQZhP9oKa8N7I,3233
|
|
14
|
+
os_normalizer/parsers/windows.py,sha256=g8aPsKMmg2M7olNf-SDWw8OGHu0dAwPYw9CwhRdBzkg,11561
|
|
15
|
+
os_normalizer/parsers/network/__init__.py,sha256=-zKHQAj2DRj4N5R5bNmZpO7LeWGsvI_0OQInrs2ZWn4,1848
|
|
16
|
+
os_normalizer/parsers/network/cisco.py,sha256=oRnuN9aVevgwx4g9o-XOqYMc19I-jOPsAQvVVQ_GI-s,3521
|
|
17
|
+
os_normalizer/parsers/network/fortinet.py,sha256=ex004jd4V6jXZKNxIXiU5Hlnt60aeD98aZNAC5dKETo,2157
|
|
18
|
+
os_normalizer/parsers/network/huawei.py,sha256=U1xjiMWnx8gyUMPZ6f-upLbJy8ATAk4-fXSVFymH5tE,1432
|
|
19
|
+
os_normalizer/parsers/network/juniper.py,sha256=XXSzPkJy2JraBI5eS8A9vV5w4othWGXVOsNw1hQfUfc,1562
|
|
20
|
+
os_normalizer/parsers/network/netgear.py,sha256=4_J7E50hqAgLK9yH3wZk3CSFFAcx1gRMdcs7CgNn2Cc,1502
|
|
21
|
+
os_normalizer-0.5.0.dist-info/METADATA,sha256=gR7vyVnbPCLJXPvFPAjbQYANrfbTjIvpitolDbWQD4w,6506
|
|
22
|
+
os_normalizer-0.5.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
23
|
+
os_normalizer-0.5.0.dist-info/licenses/LICENSE,sha256=DN0enoiHxVkJ-hxmIchPaCQWrDsZwva5LY8XvG3UK8w,1083
|
|
24
|
+
os_normalizer-0.5.0.dist-info/RECORD,,
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
os_normalizer/__init__.py,sha256=ZA2JnO3juuAn8xQBqUoUXxca10B-rE1MIuwtzDofpKs,212
|
|
2
|
-
os_normalizer/constants.py,sha256=fYva32rcHqEYKe7tKzu3_poaPWvnKJrC-tkTWbLS3sk,6049
|
|
3
|
-
os_normalizer/cpe.py,sha256=yzokJ3Iv4fNLcrCySe58IaESXBeinORVOcJGUov3Mzo,9731
|
|
4
|
-
os_normalizer/helpers.py,sha256=IymYS2NAJ6J8ngI_HL5PH2_6zN6zzIpWMx1-05D2O3c,3347
|
|
5
|
-
os_normalizer/models.py,sha256=ONEEdsjH6OsOLVNFjnHz5wME--cIuvZiLwt_oK1tXzA,6246
|
|
6
|
-
os_normalizer/os_normalizer.py,sha256=IsWxE_Yes7FQxxNhA8twNrzmeRcl8QXTxjTfn0zCTTI,10143
|
|
7
|
-
os_normalizer/parsers/__init__.py,sha256=l9kx_P7FUHy--AxygZ8Q8nlyxyoSRRTREmp40M73Gxg,324
|
|
8
|
-
os_normalizer/parsers/bsd.py,sha256=Umm7RSXjQfv6pfziJ8BYlmOc80VlLRueTrYw1iR-UjY,2018
|
|
9
|
-
os_normalizer/parsers/linux.py,sha256=kSIYZ_hRJxJieV21u8TRcWfAjYOIXlCLBSwyINkuyA4,3867
|
|
10
|
-
os_normalizer/parsers/macos.py,sha256=fU1YyiijzBdDAxUBSL2EQLhUu3JbOSx-N_KYvOg0XsI,3627
|
|
11
|
-
os_normalizer/parsers/mobile.py,sha256=Ca864JhrO9zW5fs0zbs2VcMypKIkFHqZtxpJDbi12q0,1033
|
|
12
|
-
os_normalizer/parsers/windows.py,sha256=-dWS2KJltDXThsQL78ulyn6S4Q7QW5QMRklKosvQF30,10930
|
|
13
|
-
os_normalizer/parsers/network/__init__.py,sha256=TvRz08lNDZbr6yG8O3M7cLNu0hWAbtE1y7_9SwhP4g4,1596
|
|
14
|
-
os_normalizer/parsers/network/cisco.py,sha256=ivhw85IHnHVT4sW-65F-ZGCR7yvu0mMMBfXRT4EzUfc,3203
|
|
15
|
-
os_normalizer/parsers/network/fortinet.py,sha256=i6PVRxzO_onaCvo3_eI4csXFwGp4ZpQY0d1y2-Wodn0,1783
|
|
16
|
-
os_normalizer/parsers/network/huawei.py,sha256=Su3eCRlmOCmpOPA_TGeH8gHY3-ZdXKFW4O3_W0SOPmk,1158
|
|
17
|
-
os_normalizer/parsers/network/juniper.py,sha256=gskbaY4-LYWauM9yrvGMuCxPrNBKmUfIRPd1zsUUY7w,1275
|
|
18
|
-
os_normalizer/parsers/network/netgear.py,sha256=idVD7VTxb07LdhFPwb-sT3586ARoBrd1OmWpADAZUVc,1190
|
|
19
|
-
os_normalizer-0.4.2.dist-info/METADATA,sha256=ipNU2HGD2BpwGh9jj0v5a6hYgvjR5qJN1M8apT0FwKk,6455
|
|
20
|
-
os_normalizer-0.4.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
21
|
-
os_normalizer-0.4.2.dist-info/licenses/LICENSE,sha256=DN0enoiHxVkJ-hxmIchPaCQWrDsZwva5LY8XvG3UK8w,1083
|
|
22
|
-
os_normalizer-0.4.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|