os-normalizer 0.4.1__tar.gz → 0.4.3__tar.gz

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.

Files changed (32) hide show
  1. {os_normalizer-0.4.1 → os_normalizer-0.4.3}/CHANGELOG.md +8 -0
  2. {os_normalizer-0.4.1 → os_normalizer-0.4.3}/PKG-INFO +1 -1
  3. {os_normalizer-0.4.1 → os_normalizer-0.4.3}/os_normalizer/parsers/windows.py +33 -6
  4. {os_normalizer-0.4.1 → os_normalizer-0.4.3}/pyproject.toml +1 -1
  5. {os_normalizer-0.4.1 → os_normalizer-0.4.3}/.gitignore +0 -0
  6. {os_normalizer-0.4.1 → os_normalizer-0.4.3}/.python-version +0 -0
  7. {os_normalizer-0.4.1 → os_normalizer-0.4.3}/.uv-cache/.gitignore +0 -0
  8. {os_normalizer-0.4.1 → os_normalizer-0.4.3}/.uv-cache/.lock +0 -0
  9. {os_normalizer-0.4.1 → os_normalizer-0.4.3}/.uv-cache/CACHEDIR.TAG +0 -0
  10. {os_normalizer-0.4.1 → os_normalizer-0.4.3}/.uv-cache/interpreter-v4/7e11d242fb84b9e8/939db8dea853eb17.msgpack +0 -0
  11. {os_normalizer-0.4.1 → os_normalizer-0.4.3}/.uv-cache/sdists-v9/.git +0 -0
  12. {os_normalizer-0.4.1 → os_normalizer-0.4.3}/.uv-cache/sdists-v9/.gitignore +0 -0
  13. {os_normalizer-0.4.1 → os_normalizer-0.4.3}/LICENSE +0 -0
  14. {os_normalizer-0.4.1 → os_normalizer-0.4.3}/README.md +0 -0
  15. {os_normalizer-0.4.1 → os_normalizer-0.4.3}/RELEASING.md +0 -0
  16. {os_normalizer-0.4.1 → os_normalizer-0.4.3}/os_normalizer/__init__.py +0 -0
  17. {os_normalizer-0.4.1 → os_normalizer-0.4.3}/os_normalizer/constants.py +0 -0
  18. {os_normalizer-0.4.1 → os_normalizer-0.4.3}/os_normalizer/cpe.py +0 -0
  19. {os_normalizer-0.4.1 → os_normalizer-0.4.3}/os_normalizer/helpers.py +0 -0
  20. {os_normalizer-0.4.1 → os_normalizer-0.4.3}/os_normalizer/models.py +0 -0
  21. {os_normalizer-0.4.1 → os_normalizer-0.4.3}/os_normalizer/os_normalizer.py +0 -0
  22. {os_normalizer-0.4.1 → os_normalizer-0.4.3}/os_normalizer/parsers/__init__.py +0 -0
  23. {os_normalizer-0.4.1 → os_normalizer-0.4.3}/os_normalizer/parsers/bsd.py +0 -0
  24. {os_normalizer-0.4.1 → os_normalizer-0.4.3}/os_normalizer/parsers/linux.py +0 -0
  25. {os_normalizer-0.4.1 → os_normalizer-0.4.3}/os_normalizer/parsers/macos.py +0 -0
  26. {os_normalizer-0.4.1 → os_normalizer-0.4.3}/os_normalizer/parsers/mobile.py +0 -0
  27. {os_normalizer-0.4.1 → os_normalizer-0.4.3}/os_normalizer/parsers/network/__init__.py +0 -0
  28. {os_normalizer-0.4.1 → os_normalizer-0.4.3}/os_normalizer/parsers/network/cisco.py +0 -0
  29. {os_normalizer-0.4.1 → os_normalizer-0.4.3}/os_normalizer/parsers/network/fortinet.py +0 -0
  30. {os_normalizer-0.4.1 → os_normalizer-0.4.3}/os_normalizer/parsers/network/huawei.py +0 -0
  31. {os_normalizer-0.4.1 → os_normalizer-0.4.3}/os_normalizer/parsers/network/juniper.py +0 -0
  32. {os_normalizer-0.4.1 → os_normalizer-0.4.3}/os_normalizer/parsers/network/netgear.py +0 -0
@@ -3,6 +3,14 @@
3
3
  All notable changes to this project are documented here.
4
4
  This file adheres to Keep a Changelog and Semantic Versioning.
5
5
 
6
+ ## [0.4.3] - 2025-10-20
7
+
8
+ - Fixed: Windows build parsing and inconsistent strings
9
+
10
+ ## [0.4.2] - 2025-10-20
11
+
12
+ - Fixed: Windows product fingerprinting by build number
13
+
6
14
  ## [0.4.1] - 2025-09-25
7
15
 
8
16
  - Added: Broadened Windows product aliases (e.g., Win11, Win2k) and recognized the macOS 26 codename `Tahoe`.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: os-normalizer
3
- Version: 0.4.1
3
+ Version: 0.4.3
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
@@ -20,7 +20,8 @@ if TYPE_CHECKING:
20
20
 
21
21
  VERSION_PATTERN = re.compile(r"\b(\d+)\.(\d+)\.(\d+)(?:\.(\d+))?\b")
22
22
  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)
23
+ BUILD_PATTERN = re.compile(r"\bbuild\s*(?:number\s*)?[:=\s-]*?(\d{3,5})\b", re.IGNORECASE)
24
+ KERNEL_PATTERN = re.compile(r"\bkernel\s*[:=\s-]*?(\d+)(?:\.(\d+))?", re.IGNORECASE)
24
25
  SP_PATTERN = re.compile(r"\bsp(\d)\b", re.IGNORECASE)
25
26
 
26
27
  EDITION_KEYWORDS: list[tuple[str, str]] = [
@@ -141,6 +142,13 @@ def _extract_version_state(text: str) -> VersionState:
141
142
  state.nt_minor = state.nt_minor if state.nt_minor is not None else minr
142
143
  state.explicit = True
143
144
 
145
+ if state.nt_major is None:
146
+ kernel_match = KERNEL_PATTERN.search(text)
147
+ if kernel_match:
148
+ state.nt_major = int(kernel_match.group(1))
149
+ state.nt_minor = int(kernel_match.group(2)) if kernel_match.group(2) else 0
150
+ state.explicit = True
151
+
144
152
  if state.build is None:
145
153
  build_match = BUILD_PATTERN.search(text)
146
154
  if build_match:
@@ -157,7 +165,7 @@ def _apply_build_context(state: VersionState, product: str | None, server_hint:
157
165
  return product, server_hint
158
166
 
159
167
  product_from_build, channel, is_server_build = _lookup_build(build_num, server_hint)
160
- if product_from_build and not product:
168
+ if product_from_build and (not product or _build_inference_should_replace(product, product_from_build)):
161
169
  product = product_from_build
162
170
  if is_server_build:
163
171
  server_hint = True
@@ -189,11 +197,18 @@ def _apply_version_numbers(p: OSData, defaults: ProductDefaults, state: VersionS
189
197
  def _set_kernel_version(p: OSData, defaults: ProductDefaults | None, state: VersionState) -> None:
190
198
  """Populate kernel_version using explicit tokens, build channel, or defaults."""
191
199
  kernel_version: str | None = None
192
- if state.explicit and state.nt_major is not None:
193
- if state.nt_major >= 10 and state.channel:
194
- kernel_version = state.channel
195
- elif state.nt_minor is not None:
200
+ if (
201
+ state.explicit
202
+ and state.channel
203
+ and (state.nt_major is None or state.nt_major >= 10)
204
+ and (defaults is None or defaults.kernel_version is None)
205
+ ):
206
+ kernel_version = state.channel
207
+ elif state.explicit and state.nt_major is not None:
208
+ if state.nt_minor is not None:
196
209
  kernel_version = f"{state.nt_major}.{state.nt_minor}"
210
+ elif state.nt_major >= 10 and state.channel:
211
+ kernel_version = state.channel
197
212
  if kernel_version is None and defaults and defaults.kernel_version:
198
213
  kernel_version = defaults.kernel_version
199
214
  if kernel_version:
@@ -250,6 +265,18 @@ def _lookup_build(build_num: int, server_hint: bool) -> tuple[str | None, str |
250
265
  return candidate
251
266
 
252
267
 
268
+ def _build_inference_should_replace(existing: str, inferred: str) -> bool:
269
+ """Return True when build metadata should override a detected product label."""
270
+ existing_lower = existing.lower()
271
+ inferred_lower = inferred.lower()
272
+
273
+ if existing_lower == inferred_lower:
274
+ return False
275
+ if inferred_lower.startswith(existing_lower):
276
+ return False
277
+ return True
278
+
279
+
253
280
  def _product_from_nt(major: int, minor: int, server_hint: bool) -> str | None:
254
281
  key = (major, minor)
255
282
  if server_hint and key in WINDOWS_NT_SERVER_MAP:
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "os-normalizer"
3
- version = "0.4.1"
3
+ version = "0.4.3"
4
4
  description = "Normalize raw OS strings/metadata into structured data (family, product, version, arch)."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
File without changes
File without changes
File without changes