driverclient 0.2.28__tar.gz → 0.2.29__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.
Files changed (25) hide show
  1. {driverclient-0.2.28 → driverclient-0.2.29}/PKG-INFO +1 -1
  2. {driverclient-0.2.28 → driverclient-0.2.29}/pyproject.toml +1 -1
  3. {driverclient-0.2.28 → driverclient-0.2.29}/src/driverclient/__init__.py +1 -1
  4. {driverclient-0.2.28 → driverclient-0.2.29}/src/driverclient/ops/capture.py +26 -19
  5. {driverclient-0.2.28 → driverclient-0.2.29}/.gitignore +0 -0
  6. {driverclient-0.2.28 → driverclient-0.2.29}/README.md +0 -0
  7. {driverclient-0.2.28 → driverclient-0.2.29}/src/driverclient/__main__.py +0 -0
  8. {driverclient-0.2.28 → driverclient-0.2.29}/src/driverclient/config.json +0 -0
  9. {driverclient-0.2.28 → driverclient-0.2.29}/src/driverclient/config.py +0 -0
  10. {driverclient-0.2.28 → driverclient-0.2.29}/src/driverclient/core/__init__.py +0 -0
  11. {driverclient-0.2.28 → driverclient-0.2.29}/src/driverclient/core/hardware.py +0 -0
  12. {driverclient-0.2.28 → driverclient-0.2.29}/src/driverclient/core/http.py +0 -0
  13. {driverclient-0.2.28 → driverclient-0.2.29}/src/driverclient/core/hwid.py +0 -0
  14. {driverclient-0.2.28 → driverclient-0.2.29}/src/driverclient/core/proc.py +0 -0
  15. {driverclient-0.2.28 → driverclient-0.2.29}/src/driverclient/events.py +0 -0
  16. {driverclient-0.2.28 → driverclient-0.2.29}/src/driverclient/main.py +0 -0
  17. {driverclient-0.2.28 → driverclient-0.2.29}/src/driverclient/ops/__init__.py +0 -0
  18. {driverclient-0.2.28 → driverclient-0.2.29}/src/driverclient/ops/automate.py +0 -0
  19. {driverclient-0.2.28 → driverclient-0.2.29}/src/driverclient/ops/diagnose.py +0 -0
  20. {driverclient-0.2.28 → driverclient-0.2.29}/src/driverclient/ops/download.py +0 -0
  21. {driverclient-0.2.28 → driverclient-0.2.29}/src/driverclient/ops/install.py +0 -0
  22. {driverclient-0.2.28 → driverclient-0.2.29}/src/driverclient/ops/offline.py +0 -0
  23. {driverclient-0.2.28 → driverclient-0.2.29}/src/driverclient/ops/resolve.py +0 -0
  24. {driverclient-0.2.28 → driverclient-0.2.29}/src/driverclient/ops/scan.py +0 -0
  25. {driverclient-0.2.28 → driverclient-0.2.29}/src/driverclient/py.typed +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: driverclient
3
- Version: 0.2.28
3
+ Version: 0.2.29
4
4
  Summary: Driver Server client with an embeddable connector for config injection at runtime.
5
5
  Project-URL: Homepage, https://example.com/driverclient
6
6
  Author-email: Raja Sanaullah <sanaullah@99technologies.com>
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "driverclient"
7
- version = "0.2.28"
7
+ version = "0.2.29"
8
8
  description = "Driver Server client with an embeddable connector for config injection at runtime."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -26,7 +26,7 @@ from driverclient.main import run as _run
26
26
 
27
27
  __all__ = ["ClientEvent", "DriverClient"]
28
28
 
29
- __version__ = "0.2.28"
29
+ __version__ = "0.2.29"
30
30
 
31
31
 
32
32
  class DriverClient:
@@ -97,9 +97,6 @@ def _machine_meta() -> dict:
97
97
  "machine_id": machine_id,
98
98
  }
99
99
 
100
-
101
- _WINDOWS_INF = Path("C:\\Windows\\INF")
102
-
103
100
  _PNPUTIL_KEYS: dict[str, str] = {
104
101
  "published name": "published_name",
105
102
  "original name": "original_name",
@@ -349,12 +346,13 @@ def wu_update(force: bool = False) -> CaptureResult:
349
346
  **skip_reasons,
350
347
  )
351
348
 
349
+ baseline = _snapshot_published_names(cfg)
352
350
  trigger = _trigger_wu()
353
351
  if trigger is None:
354
352
  return CaptureResult(still_missing=len(wu_hwids))
355
353
 
356
354
  wu_start = datetime.now(timezone.utc)
357
- total = _poll_and_submit_incremental(wu_start, cfg, trigger)
355
+ total = _poll_and_submit_incremental(wu_start, cfg, trigger, baseline)
358
356
  total.wu_triggered = True
359
357
  total.still_missing = max(0, len(wu_hwids) - total.submitted)
360
358
  total.reboot_required = _wu_reboot_pending()
@@ -383,12 +381,13 @@ def wu_full() -> CaptureResult:
383
381
  "windows_update", "[wu-full] Triggering full Windows Update scan (no HWID filtering)…"
384
382
  )
385
383
 
384
+ baseline = _snapshot_published_names(cfg)
386
385
  trigger = _trigger_wu()
387
386
  if trigger is None:
388
387
  return CaptureResult()
389
388
 
390
389
  wu_start = datetime.now(timezone.utc)
391
- total = _poll_and_submit_incremental(wu_start, cfg, trigger)
390
+ total = _poll_and_submit_incremental(wu_start, cfg, trigger, baseline)
392
391
  total.wu_triggered = True
393
392
  _post_wu_session(cfg, wu_start, [], total.submitted)
394
393
  events.done(
@@ -528,17 +527,25 @@ def _parse_enum_drivers(output: str) -> list[dict]:
528
527
  return packages
529
528
 
530
529
 
531
- def _enumerate_packages_since(cutoff: datetime, cfg: dict) -> list[dict]:
532
- """Return packages whose C:\\Windows\\INF mtime >= cutoff."""
533
- result = []
534
- for pkg in _enumerate_all_packages(cfg):
535
- inf_path = _WINDOWS_INF / pkg["published_name"]
536
- if not inf_path.exists():
537
- continue
538
- mtime = datetime.fromtimestamp(inf_path.stat().st_mtime, tz=timezone.utc)
539
- if mtime >= cutoff:
540
- result.append(pkg)
541
- return result
530
+ def _snapshot_published_names(cfg: dict) -> set[str]:
531
+ """Published names (oemNN.inf) already in the driver store — the baseline a
532
+ WU run's new-package detection diffs against. Must be taken BEFORE
533
+ triggering WU so nothing it installs is mistaken for pre-existing."""
534
+ return {p["published_name"] for p in _enumerate_all_packages(cfg) if p.get("published_name")}
535
+
536
+
537
+ def _enumerate_new_packages(baseline: set[str], cfg: dict) -> list[dict]:
538
+ """Return packages present now that weren't in the pre-WU baseline.
539
+
540
+ Published names are assigned once by Windows and never reused while a
541
+ package stays in the store, so "not in baseline" is a robust new-package
542
+ signal. The previous approach compared each INF's mtime under
543
+ C:\\Windows\\INF against the WU start time — but that mtime can predate the
544
+ run (e.g. Windows already staged the file) or otherwise not bump the way
545
+ expected, silently dropping a genuinely new package (e.g. a discrete AMD
546
+ display driver landing via WU alongside an already-captured Intel one)
547
+ from ever being detected as new, so it was never submitted."""
548
+ return [p for p in _enumerate_all_packages(cfg) if p.get("published_name") not in baseline]
542
549
 
543
550
 
544
551
  def _published_names_for_hwids(
@@ -878,7 +885,7 @@ def _drain_wu_log(trigger: "_WuTrigger | None", pos: int) -> int:
878
885
 
879
886
 
880
887
  def _poll_and_submit_incremental(
881
- wu_start: datetime, cfg: dict, trigger: "_WuTrigger | None"
888
+ wu_start: datetime, cfg: dict, trigger: "_WuTrigger | None", baseline: set[str]
882
889
  ) -> CaptureResult:
883
890
  """
884
891
  Wait on Windows Update, submitting each new DriverStore package as it lands.
@@ -913,7 +920,7 @@ def _poll_and_submit_incremental(
913
920
 
914
921
  while datetime.now(timezone.utc) < deadline:
915
922
  log_pos = _drain_wu_log(trigger, log_pos) # surface WU's live phase
916
- all_new = _enumerate_packages_since(wu_start, cfg)
923
+ all_new = _enumerate_new_packages(baseline, cfg)
917
924
  new_batch = [p for p in all_new if p.get("published_name", "") not in seen]
918
925
 
919
926
  if new_batch:
@@ -1214,4 +1221,4 @@ def _upload_worker(upload_q: queue.Queue, counts: dict, lock: threading.Lock, cf
1214
1221
  # Extension selection was removed: capture now packs every file
1215
1222
  # pnputil /export-driver produces (see _do_export), so the dump_extensions /
1216
1223
  # dump_extensions_overrides config keys are no longer consulted — filtering by
1217
- # extension is what caused incomplete packages (broken link D).
1224
+ # extension is what caused incomplete packages (broken link D).
File without changes
File without changes