From a8c1cdf0954043fcd2297057902a610699e672f7 Mon Sep 17 00:00:00 2001
From: Oscar Krause <oscar.krause@collinwebdesigns.de>
Date: Fri, 11 Apr 2025 14:10:26 +0200
Subject: [PATCH 01/14] updated create_driver_matrix_json.py

---
 test/create_driver_matrix_json.py | 56 ++++++++++++-------------------
 1 file changed, 21 insertions(+), 35 deletions(-)

diff --git a/test/create_driver_matrix_json.py b/test/create_driver_matrix_json.py
index 2047d2e..a2afd9f 100644
--- a/test/create_driver_matrix_json.py
+++ b/test/create_driver_matrix_json.py
@@ -6,7 +6,7 @@ logger.setLevel(logging.INFO)
 
 URL = 'https://docs.nvidia.com/vgpu/index.html'
 
-BRANCH_STATUS_KEY, SOFTWARE_BRANCH_KEY, = 'vGPU Branch Status', 'vGPU Software Branch'
+BRANCH_STATUS_KEY = 'vGPU Branch Status'
 VGPU_KEY, GRID_KEY, DRIVER_BRANCH_KEY = 'vGPU Software', 'vGPU Software', 'Driver Branch'
 LINUX_VGPU_MANAGER_KEY, LINUX_DRIVER_KEY = 'Linux vGPU Manager', 'Linux Driver'
 WINDOWS_VGPU_MANAGER_KEY, WINDOWS_DRIVER_KEY = 'Windows vGPU Manager', 'Windows Driver'
@@ -26,12 +26,15 @@ def __driver_versions(html: 'BeautifulSoup'):
 
     # find wrapper for "DriverVersions" and find tables
     data = html.find('div', {'id': 'driver-versions'})
-    items = data.findAll('bsp-accordion', {'class': 'Accordion-items-item'})
+    items = data.find_all('bsp-accordion', {'class': 'Accordion-items-item'})
     for item in items:
         software_branch = item.find('div', {'class': 'Accordion-items-item-title'}).text.strip()
         software_branch = software_branch.replace(' Releases', '')
         matrix_key = software_branch.lower()
 
+        branch_status = item.find('a', href=True, string='Branch status')
+        branch_status = branch_status.next_sibling.replace(':', '').strip()
+
         # driver version info from table-heads (ths) and table-rows (trs)
         table = item.find('table')
         ths, trs = table.find_all('th'), table.find_all('tr')
@@ -42,48 +45,20 @@ def __driver_versions(html: 'BeautifulSoup'):
                 continue
             # create dict with table-heads as key and cell content as value
             x = {headers[i]: __strip(cell.text) for i, cell in enumerate(tds)}
+            x.setdefault(BRANCH_STATUS_KEY, branch_status)
             releases.append(x)
 
         # add to matrix
         MATRIX.update({matrix_key: {JSON_RELEASES_KEY: releases}})
 
 
-def __release_branches(html: 'BeautifulSoup'):
-    # find wrapper for "AllReleaseBranches" and find table
-    data = html.find('div', {'id': 'all-release-branches'})
-    table = data.find('table')
-
-    # branch releases info from table-heads (ths) and table-rows (trs)
-    ths, trs = table.find_all('th'), table.find_all('tr')
-    headers = [header.text.strip() for header in ths]
-    for trs in trs:
-        tds = trs.find_all('td')
-        if len(tds) == 0:  # skip empty
-            continue
-        # create dict with table-heads as key and cell content as value
-        x = {headers[i]: cell.text.strip() for i, cell in enumerate(tds)}
-
-        # get matrix_key
-        software_branch = x.get(SOFTWARE_BRANCH_KEY)
-        matrix_key = software_branch.lower()
-
-        # add to matrix
-        MATRIX.update({matrix_key: MATRIX.get(matrix_key) | x})
-
-
 def __debug():
     # print table head
-    s = f'{SOFTWARE_BRANCH_KEY:^21} | {BRANCH_STATUS_KEY:^21} | {VGPU_KEY:^13} | {LINUX_VGPU_MANAGER_KEY:^21} | {LINUX_DRIVER_KEY:^21} | {WINDOWS_VGPU_MANAGER_KEY:^21} | {WINDOWS_DRIVER_KEY:^21} | {RELEASE_DATE_KEY:>21} | {EOL_KEY:>21}'
+    s = f'{VGPU_KEY:^13} | {LINUX_VGPU_MANAGER_KEY:^21} | {LINUX_DRIVER_KEY:^21} | {WINDOWS_VGPU_MANAGER_KEY:^21} | {WINDOWS_DRIVER_KEY:^21} | {RELEASE_DATE_KEY:>21} | {BRANCH_STATUS_KEY:^21}'
     print(s)
 
     # iterate over dict & format some variables to not overload table
     for idx, (key, branch) in enumerate(MATRIX.items()):
-        branch_status = branch.get(BRANCH_STATUS_KEY)
-        branch_status = branch_status.replace('Branch ', '')
-        branch_status = branch_status.replace('Long-Term Support', 'LTS')
-        branch_status = branch_status.replace('Production', 'Prod.')
-
-        software_branch = branch.get(SOFTWARE_BRANCH_KEY).replace('NVIDIA ', '')
         for release in branch.get(JSON_RELEASES_KEY):
             version = release.get(VGPU_KEY, release.get(GRID_KEY, ''))
             linux_manager = release.get(LINUX_VGPU_MANAGER_KEY, release.get(ALT_VGPU_MANAGER_KEY, ''))
@@ -92,13 +67,25 @@ def __debug():
             windows_driver = release.get(WINDOWS_DRIVER_KEY)
             release_date = release.get(RELEASE_DATE_KEY)
             is_latest = release.get(VGPU_KEY) == branch.get(LATEST_KEY)
+            branch_status = __parse_branch_status(release.get(BRANCH_STATUS_KEY, ''))
 
             version = f'{version} *' if is_latest else version
-            eol = branch.get(EOL_KEY) if is_latest else ''
-            s = f'{software_branch:^21} | {branch_status:^21} | {version:<13} | {linux_manager:<21} | {linux_driver:<21} | {windows_manager:<21} | {windows_driver:<21} | {release_date:>21} | {eol:>21}'
+            s = f'{version:<13} | {linux_manager:<21} | {linux_driver:<21} | {windows_manager:<21} | {windows_driver:<21} | {release_date:>21} | {branch_status:^21}'
             print(s)
 
 
+def __parse_branch_status(string: str) -> str:
+    string = string.replace('Production Branch', 'Prod. -')
+    string = string.replace('Long-Term Support Branch', 'LTS -')
+
+    string = string.replace('supported until', '')
+
+    string = string.replace('EOL since', 'EOL - ')
+    string = string.replace('EOL from', 'EOL -')
+
+    return string
+
+
 def __dump(filename: str):
     import json
 
@@ -128,7 +115,6 @@ if __name__ == '__main__':
 
     # build matrix
     __driver_versions(soup)
-    __release_branches(soup)
 
     # debug output
     __debug()

From 477e5abbca37b03b894788f9ae3234c8f7991220 Mon Sep 17 00:00:00 2001
From: Oscar Krause <oscar.krause@collinwebdesigns.de>
Date: Wed, 16 Apr 2025 12:12:23 +0200
Subject: [PATCH 02/14] refactored test pipeline to test different python
 versions

---
 .gitlab-ci.yml | 18 ++++++++++--------
 1 file changed, 10 insertions(+), 8 deletions(-)

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index dd97c6f..46e3a4e 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -126,8 +126,8 @@ build:pacman:
     paths:
       - "*.pkg.tar.zst"
 
-test:
-  image: python:3.12-slim-bookworm
+test:python:
+  image: $IMAGE
   stage: test
   interruptible: true
   rules:
@@ -142,17 +142,19 @@ test:
     DATABASE: sqlite:///../app/db.sqlite
   parallel:
     matrix:
-      - REQUIREMENTS:
-          - 'requirements.txt'
-#          - '.DEBIAN/requirements-bookworm-12.txt'
-#          - '.DEBIAN/requirements-ubuntu-24.04.txt'
-#          - '.DEBIAN/requirements-ubuntu-24.10.txt'
+      - IMAGE:
+#          - python:3.14-alpine
+#          - python:3.13-alpine
+          - python:3.12-alpine
+#          - python:3.11-alpine
+#          - python:3.10-alpine
+#          - python:3.9-alpine
   before_script:
     - apt-get update && apt-get install -y python3-dev python3-pip python3-venv gcc
     - python3 -m venv venv
     - source venv/bin/activate
     - pip install --upgrade pip
-    - pip install -r $REQUIREMENTS
+    - pip install -r requirements.txt
     - pip install pytest pytest-cov pytest-custom_exit_code httpx
     - mkdir -p app/cert
     - openssl genrsa -out app/cert/instance.private.pem 2048

From 6fb03309a545f4b826a554bb1c7a6cc9a5ea1b97 Mon Sep 17 00:00:00 2001
From: Oscar Krause <oscar.krause@collinwebdesigns.de>
Date: Wed, 16 Apr 2025 12:23:21 +0200
Subject: [PATCH 03/14] ci improvements

---
 .gitlab-ci.yml | 15 +++++++--------
 1 file changed, 7 insertions(+), 8 deletions(-)

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 46e3a4e..1a66256 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -298,15 +298,12 @@ gemnasium-python-dependency_scanning:
     - if: $CI_PIPELINE_SOURCE == "merge_request_event"
     - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
 
-.deploy:
-  rules:
-    - if: $CI_COMMIT_TAG
-
 deploy:docker:
-  extends: .deploy
   image: docker:dind
   stage: deploy
   tags: [ docker ]
+  rules:
+    - if: $CI_COMMIT_TAG
   before_script:
     - echo "Building docker image for commit $CI_COMMIT_SHA with version $CI_COMMIT_REF_NAME"
     - docker buildx inspect
@@ -325,9 +322,10 @@ deploy:docker:
 
 deploy:apt:
   # doc: https://git.collinwebdesigns.de/help/user/packages/debian_repository/index.md#install-a-package
-  extends: .deploy
   image: debian:bookworm-slim
   stage: deploy
+  rules:
+    - if: $CI_COMMIT_TAG
   needs:
     - job: build:apt
       artifacts: true
@@ -364,9 +362,10 @@ deploy:apt:
     - 'curl --header "JOB-TOKEN: $CI_JOB_TOKEN" --upload-file ${EXPORT_NAME} "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/${PACKAGE_NAME}/${PACKAGE_VERSION}/${EXPORT_NAME}"'
 
 deploy:pacman:
-  extends: .deploy
   image: archlinux:base-devel
   stage: deploy
+  rules:
+    - if: $CI_COMMIT_TAG
   needs:
     - job: build:pacman
       artifacts: true
@@ -387,7 +386,7 @@ deploy:pacman:
 release:
   image: registry.gitlab.com/gitlab-org/release-cli:latest
   stage: .post
-  needs: [ test ]
+  needs: [ test:python ]
   rules:
     - if: $CI_COMMIT_TAG
   script:

From 52cd34cb5cfc92abe7b7c70e053fbc1a4e5a3124 Mon Sep 17 00:00:00 2001
From: Oscar Krause <oscar.krause@collinwebdesigns.de>
Date: Wed, 16 Apr 2025 12:24:19 +0200
Subject: [PATCH 04/14] ci improvements

---
 .gitlab-ci.yml | 21 ++++++++++-----------
 1 file changed, 10 insertions(+), 11 deletions(-)

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 1a66256..240782a 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -167,7 +167,8 @@ test:python:
       dotenv: version.env
       junit: ['**/report.xml']
 
-.test:apt:
+test:apt:
+  image: $IMAGE
   stage: test
   rules:
     - if: $CI_COMMIT_BRANCH && $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH
@@ -175,6 +176,14 @@ test:python:
         - app/**/*
         - .DEBIAN/**/*
     - if: $CI_PIPELINE_SOURCE == 'merge_request_event'
+  parallel:
+    matrix:
+      - IMAGE:
+          - debian:trixie-slim # EOL: t.b.a.
+          - debian:bookworm-slim # EOL: June 06, 2026
+          - debian:bookworm-slim # EOL: June 06, 2026
+          - ubuntu:24.04 # EOL: April 2036
+          - ubuntu:24.10
   needs:
     - job: build:apt
       artifacts: true
@@ -206,16 +215,6 @@ test:python:
     - apt-get purge -qq -y fastapi-dls
     - apt-get autoremove -qq -y && apt-get clean -qq
 
-test:apt:
-  extends: .test:apt
-  image: $IMAGE
-  parallel:
-    matrix:
-      - IMAGE:
-          - debian:bookworm-slim # EOL: June 06, 2026
-          - ubuntu:24.04 # EOL: April 2036
-          - ubuntu:24.10
-
 test:pacman:archlinux:
   image: archlinux:base
   rules:

From 67f2d18a95e04ead81c9b3c30ea2468d0beab2c3 Mon Sep 17 00:00:00 2001
From: Oscar Krause <oscar.krause@collinwebdesigns.de>
Date: Wed, 16 Apr 2025 12:25:37 +0200
Subject: [PATCH 05/14] requirements.txt updated

---
 requirements.txt | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/requirements.txt b/requirements.txt
index 6819866..734ff42 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,8 +1,8 @@
 fastapi==0.115.12
-uvicorn[standard]==0.34.0
+uvicorn[standard]==0.34.1
 python-jose[cryptography]==3.4.0
 cryptography==44.0.2
 python-dateutil==2.9.0
 sqlalchemy==2.0.40
-markdown==3.7
+markdown==3.8
 python-dotenv==1.1.0

From 5d2bff88d8f64fdfd4c53e7df8975b4c75898a1e Mon Sep 17 00:00:00 2001
From: Oscar Krause <oscar.krause@collinwebdesigns.de>
Date: Wed, 16 Apr 2025 12:35:24 +0200
Subject: [PATCH 06/14] fixes

---
 .gitlab-ci.yml | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 240782a..037bd4e 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -132,7 +132,6 @@ test:python:
   interruptible: true
   rules:
     - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
-    - if: $CI_COMMIT_TAG
     - if: $CI_PIPELINE_SOURCE == "merge_request_event"
     - if: $CI_COMMIT_BRANCH && $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH
       changes:
@@ -150,7 +149,7 @@ test:python:
 #          - python:3.10-alpine
 #          - python:3.9-alpine
   before_script:
-    - apt-get update && apt-get install -y python3-dev python3-pip python3-venv gcc
+    - apk --no-cache add openssl
     - python3 -m venv venv
     - source venv/bin/activate
     - pip install --upgrade pip
@@ -385,7 +384,7 @@ deploy:pacman:
 release:
   image: registry.gitlab.com/gitlab-org/release-cli:latest
   stage: .post
-  needs: [ test:python ]
+  needs: [ build:docker, build:apt, build:pacman ]
   rules:
     - if: $CI_COMMIT_TAG
   script:

From a996504c509506361a22b9cfc285e6fafd0d63cc Mon Sep 17 00:00:00 2001
From: Oscar Krause <oscar.krause@collinwebdesigns.de>
Date: Wed, 16 Apr 2025 12:44:58 +0200
Subject: [PATCH 07/14] test python3.13 and 3.11

---
 .gitlab-ci.yml | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 037bd4e..09a4d83 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -143,9 +143,9 @@ test:python:
     matrix:
       - IMAGE:
 #          - python:3.14-alpine
-#          - python:3.13-alpine
+          - python:3.13-alpine
           - python:3.12-alpine
-#          - python:3.11-alpine
+          - python:3.11-alpine
 #          - python:3.10-alpine
 #          - python:3.9-alpine
   before_script:
@@ -163,7 +163,6 @@ test:python:
     - python -m pytest main.py --junitxml=report.xml
   artifacts:
     reports:
-      dotenv: version.env
       junit: ['**/report.xml']
 
 test:apt:

From 3fe3429986e21038d80ef4f498b5e26bc0cb03dd Mon Sep 17 00:00:00 2001
From: Oscar Krause <oscar.krause@collinwebdesigns.de>
Date: Wed, 16 Apr 2025 12:54:24 +0200
Subject: [PATCH 08/14] added some python versions and added EOL

---
 .gitlab-ci.yml | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 09a4d83..0927a22 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -142,12 +142,13 @@ test:python:
   parallel:
     matrix:
       - IMAGE:
-#          - python:3.14-alpine
-          - python:3.13-alpine
-          - python:3.12-alpine
-          - python:3.11-alpine
-#          - python:3.10-alpine
-#          - python:3.9-alpine
+          # https://devguide.python.org/versions/#supported-versions
+          - python:3.14-alpine  # EOL 2030-10
+          - python:3.13-alpine  # EOL 2029-10
+          - python:3.12-alpine  # EOL 2028-10
+          - python:3.11-alpine  # EOL 2027-10
+          - python:3.10-alpine  # EOL 2026-10
+          - python:3.9-alpine  # EOL 2025-10
   before_script:
     - apk --no-cache add openssl
     - python3 -m venv venv

From df506e8591544bf88b2739cc8dcd8de923060df6 Mon Sep 17 00:00:00 2001
From: Oscar Krause <oscar.krause@collinwebdesigns.de>
Date: Wed, 16 Apr 2025 13:56:36 +0200
Subject: [PATCH 09/14] removed unsupported python versions

---
 .gitlab-ci.yml | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 0927a22..c84537c 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -143,12 +143,12 @@ test:python:
     matrix:
       - IMAGE:
           # https://devguide.python.org/versions/#supported-versions
-          - python:3.14-alpine  # EOL 2030-10
+          - python:3.14-rc-alpine  # EOL 2030-10
           - python:3.13-alpine  # EOL 2029-10
           - python:3.12-alpine  # EOL 2028-10
           - python:3.11-alpine  # EOL 2027-10
-          - python:3.10-alpine  # EOL 2026-10
-          - python:3.9-alpine  # EOL 2025-10
+#          - python:3.10-alpine  # EOL 2026-10 => ImportError: cannot import name 'UTC' from 'datetime'
+#          - python:3.9-alpine  # EOL 2025-10 => ImportError: cannot import name 'UTC' from 'datetime'
   before_script:
     - apk --no-cache add openssl
     - python3 -m venv venv

From 4f772006283dec107797206844fd05d2e48d3176 Mon Sep 17 00:00:00 2001
From: Oscar Krause <oscar.krause@collinwebdesigns.de>
Date: Wed, 16 Apr 2025 14:04:11 +0200
Subject: [PATCH 10/14] code styling

---
 README.md | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/README.md b/README.md
index 25d3588..dd64223 100644
--- a/README.md
+++ b/README.md
@@ -795,13 +795,13 @@ Thanks to vGPU community and all who uses this project and report bugs.
 
 Special thanks to:
 
-- @samicrusader who created build file for **ArchLinux**
-- @cyrus who wrote the section for **openSUSE**
-- @midi who wrote the section for **unRAID**
-- @polloloco who wrote the *[NVIDIA vGPU Guide](https://gitlab.com/polloloco/vgpu-proxmox)*
-- @DualCoder who creates the `vgpu_unlock` functionality [vgpu_unlock](https://github.com/DualCoder/vgpu_unlock)
-- Krutav Shah who wrote the [vGPU_Unlock Wiki](https://docs.google.com/document/d/1pzrWJ9h-zANCtyqRgS7Vzla0Y8Ea2-5z2HEi4X75d2Q/)
-- Wim van 't Hoog for the [Proxmox All-In-One Installer Script](https://wvthoog.nl/proxmox-vgpu-v3/)
-- @mrzenc who wrote [fastapi-dls-nixos](https://github.com/mrzenc/fastapi-dls-nixos)
+- `samicrusader` who created build file for **ArchLinux**
+- `cyrus` who wrote the section for **openSUSE**
+- `midi` who wrote the section for **unRAID**
+- `polloloco` who wrote the *[NVIDIA vGPU Guide](https://gitlab.com/polloloco/vgpu-proxmox)*
+- `DualCoder` who creates the `vgpu_unlock` functionality [vgpu_unlock](https://github.com/DualCoder/vgpu_unlock)
+- `Krutav Shah` who wrote the [vGPU_Unlock Wiki](https://docs.google.com/document/d/1pzrWJ9h-zANCtyqRgS7Vzla0Y8Ea2-5z2HEi4X75d2Q/)
+- `Wim van 't Hoog` for the [Proxmox All-In-One Installer Script](https://wvthoog.nl/proxmox-vgpu-v3/)
+- `mrzenc` who wrote [fastapi-dls-nixos](https://github.com/mrzenc/fastapi-dls-nixos)
 
 And thanks to all people who contributed to all these libraries!

From 9f417b61a9e03cb573f7232870e711f0c9114990 Mon Sep 17 00:00:00 2001
From: Oscar Krause <oscar.krause@collinwebdesigns.de>
Date: Wed, 16 Apr 2025 14:07:14 +0200
Subject: [PATCH 11/14] fixes

---
 .gitlab-ci.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 8889988..f2e15e9 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -137,7 +137,7 @@ test:python:
     matrix:
       - IMAGE:
           # https://devguide.python.org/versions/#supported-versions
-          - python:3.14-rc-alpine  # EOL 2030-10
+#          - python:3.14-rc-alpine  # EOL 2030-10 =>  uvicorn does not support 3.14 yet
           - python:3.13-alpine  # EOL 2029-10
           - python:3.12-alpine  # EOL 2028-10
           - python:3.11-alpine  # EOL 2027-10

From cea7a01b543d43d78d9aac43327fbbb37d7aece4 Mon Sep 17 00:00:00 2001
From: Oscar Krause <oscar.krause@collinwebdesigns.de>
Date: Wed, 16 Apr 2025 14:12:15 +0200
Subject: [PATCH 12/14] code styling

---
 app/orm.py  |  4 ++--
 app/util.py | 18 +++++++++---------
 2 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/app/orm.py b/app/orm.py
index e2dd0bc..89235b0 100644
--- a/app/orm.py
+++ b/app/orm.py
@@ -5,7 +5,7 @@ from sqlalchemy import Column, VARCHAR, CHAR, ForeignKey, DATETIME, update, and_
 from sqlalchemy.engine import Engine
 from sqlalchemy.orm import sessionmaker, declarative_base
 
-from util import NV
+from util import DriverMatrix
 
 Base = declarative_base()
 
@@ -25,7 +25,7 @@ class Origin(Base):
         return f'Origin(origin_ref={self.origin_ref}, hostname={self.hostname})'
 
     def serialize(self) -> dict:
-        _ = NV().find(self.guest_driver_version)
+        _ = DriverMatrix().find(self.guest_driver_version)
 
         return {
             'origin_ref': self.origin_ref,
diff --git a/app/util.py b/app/util.py
index 1aae17b..f6a2efb 100644
--- a/app/util.py
+++ b/app/util.py
@@ -1,4 +1,5 @@
 import logging
+from json import load as json_load
 
 from cryptography.hazmat.primitives import serialization
 from cryptography.hazmat.primitives.asymmetric.rsa import RSAPrivateKey, RSAPublicKey, generate_private_key
@@ -84,29 +85,28 @@ def load_file(filename: str) -> bytes:
     return content
 
 
-class NV:
+class DriverMatrix:
     __DRIVER_MATRIX_FILENAME = 'static/driver_matrix.json'
     __DRIVER_MATRIX: None | dict = None  # https://docs.nvidia.com/grid/ => "Driver Versions"
 
     def __init__(self):
         self.log = logging.getLogger(self.__class__.__name__)
 
-        if NV.__DRIVER_MATRIX is None:
-            from json import load as json_load
+        if DriverMatrix.__DRIVER_MATRIX is None:
             try:
-                file = open(NV.__DRIVER_MATRIX_FILENAME)
-                NV.__DRIVER_MATRIX = json_load(file)
+                file = open(DriverMatrix.__DRIVER_MATRIX_FILENAME)
+                DriverMatrix.__DRIVER_MATRIX = json_load(file)
                 file.close()
-                self.log.debug(f'Successfully loaded "{NV.__DRIVER_MATRIX_FILENAME}".')
+                self.log.debug(f'Successfully loaded "{DriverMatrix.__DRIVER_MATRIX_FILENAME}".')
             except Exception as e:
-                NV.__DRIVER_MATRIX = {}  # init empty dict to not try open file everytime, just when restarting app
+                DriverMatrix.__DRIVER_MATRIX = {}  # init empty dict to not try open file everytime, just when restarting app
                 # self.log.warning(f'Failed to load "{NV.__DRIVER_MATRIX_FILENAME}": {e}')
 
     @staticmethod
     def find(version: str) -> dict | None:
-        if NV.__DRIVER_MATRIX is None:
+        if DriverMatrix.__DRIVER_MATRIX is None:
             return None
-        for idx, (key, branch) in enumerate(NV.__DRIVER_MATRIX.items()):
+        for idx, (key, branch) in enumerate(DriverMatrix.__DRIVER_MATRIX.items()):
             for release in branch.get('$releases'):
                 linux_driver = release.get('Linux Driver')
                 windows_driver = release.get('Windows Driver')

From 1d3255188e25cec76493377f27ae660b82db4dc8 Mon Sep 17 00:00:00 2001
From: Oscar Krause <oscar.krause@collinwebdesigns.de>
Date: Wed, 16 Apr 2025 14:12:40 +0200
Subject: [PATCH 13/14] code styling

---
 app/util.py | 15 ++++++++-------
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/app/util.py b/app/util.py
index f6a2efb..3866d69 100644
--- a/app/util.py
+++ b/app/util.py
@@ -8,6 +8,14 @@ from cryptography.hazmat.primitives.serialization import load_pem_private_key, l
 logging.basicConfig()
 
 
+def load_file(filename: str) -> bytes:
+    log = logging.getLogger(f'{__name__}')
+    log.debug(f'Loading contents of file "{filename}')
+    with open(filename, 'rb') as file:
+        content = file.read()
+    return content
+
+
 class PrivateKey:
 
     def __init__(self, data: bytes):
@@ -77,13 +85,6 @@ class PublicKey:
             format=serialization.PublicFormat.SubjectPublicKeyInfo
         )
 
-def load_file(filename: str) -> bytes:
-    log = logging.getLogger(f'{__name__}')
-    log.debug(f'Loading contents of file "{filename}')
-    with open(filename, 'rb') as file:
-        content = file.read()
-    return content
-
 
 class DriverMatrix:
     __DRIVER_MATRIX_FILENAME = 'static/driver_matrix.json'

From cd5c2a6cb1c641fba8e205542a7be6c5a43bb7ed Mon Sep 17 00:00:00 2001
From: Oscar Krause <oscar.krause@collinwebdesigns.de>
Date: Wed, 16 Apr 2025 14:18:04 +0200
Subject: [PATCH 14/14] code styling

---
 app/util.py | 19 +++++++++++--------
 1 file changed, 11 insertions(+), 8 deletions(-)

diff --git a/app/util.py b/app/util.py
index 3866d69..c6c93d0 100644
--- a/app/util.py
+++ b/app/util.py
@@ -94,14 +94,17 @@ class DriverMatrix:
         self.log = logging.getLogger(self.__class__.__name__)
 
         if DriverMatrix.__DRIVER_MATRIX is None:
-            try:
-                file = open(DriverMatrix.__DRIVER_MATRIX_FILENAME)
-                DriverMatrix.__DRIVER_MATRIX = json_load(file)
-                file.close()
-                self.log.debug(f'Successfully loaded "{DriverMatrix.__DRIVER_MATRIX_FILENAME}".')
-            except Exception as e:
-                DriverMatrix.__DRIVER_MATRIX = {}  # init empty dict to not try open file everytime, just when restarting app
-                # self.log.warning(f'Failed to load "{NV.__DRIVER_MATRIX_FILENAME}": {e}')
+            self.__load()
+
+    def __load(self):
+        try:
+            file = open(DriverMatrix.__DRIVER_MATRIX_FILENAME)
+            DriverMatrix.__DRIVER_MATRIX = json_load(file)
+            file.close()
+            self.log.debug(f'Successfully loaded "{DriverMatrix.__DRIVER_MATRIX_FILENAME}".')
+        except Exception as e:
+            DriverMatrix.__DRIVER_MATRIX = {}  # init empty dict to not try open file everytime, just when restarting app
+            # self.log.warning(f'Failed to load "{NV.__DRIVER_MATRIX_FILENAME}": {e}')
 
     @staticmethod
     def find(version: str) -> dict | None: