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.

@@ -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
- if not product:
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 state.explicit and state.nt_major is not None:
196
- if state.nt_major >= 10 and state.channel:
197
- kernel_version = state.channel
198
- elif state.nt_minor is not None:
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 _build_inference_is_more_precise(existing: str, inferred: str) -> bool:
257
- """Return True when the build map provides a more specific client SKU."""
258
- if existing in {"Windows 10", "Windows 10/11"} and inferred.startswith("Windows 11"):
259
- return True
260
- if existing == "Windows 10/11" and inferred == "Windows 10":
261
- return True
262
- return False
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
- ) -> str:
293
+ ) -> PrecisionLevel:
278
294
  if build:
279
- return "build"
295
+ return PrecisionLevel.BUILD
280
296
  if patch is not None and patch != 0:
281
- return "patch"
297
+ return PrecisionLevel.PATCH
282
298
  if minor is not None:
283
- return "minor"
299
+ return PrecisionLevel.MINOR
284
300
  if major is not None:
285
- return "major"
286
- return "product"
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.4.2
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,,