From ed7594f71534695a69966bf3519d1b612ce60672 Mon Sep 17 00:00:00 2001 From: Joseph Date: Sat, 10 Jan 2026 21:20:00 +0100 Subject: [PATCH 01/19] This is a combination of 2 commits. docs: update instructions --- .gitignore | 9 ++++++--- docs/FLASHING.md | 12 ++++++++---- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/.gitignore b/.gitignore index f61a68a..eaeb236 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ -# basic +# general __pycache__ /dist .venv @@ -8,7 +8,10 @@ __pycache__ .ruff_cache .ropeproject -# git subrepos +# misc +.DS_Store + +# subrepos /android_* /*_kernel_* /clang* @@ -16,7 +19,7 @@ __pycache__ /AnyKernel3 /KernelSU -# misc local artifacts +# local artifacts /*.log /kernel /assets diff --git a/docs/FLASHING.md b/docs/FLASHING.md index 6296171..25454aa 100755 --- a/docs/FLASHING.md +++ b/docs/FLASHING.md @@ -20,7 +20,7 @@ Backup should be made with removed lockscreen passwords/fingerprints/PINs. Other Listed below files are required: -- compiled kernel, obviously; +- the compiled kernel ZIP; - ROM; - Magisk or KernelSU; - TWRP, the special [build](https://sourceforge.net/projects/op5-5t/files/Android-12/TWRP/twrp-3.7.0_12-5-dyn-cheeseburger_dumpling.img/download) by faoliveira78 (supports operations with encrypted and dynamic partitions); @@ -53,7 +53,7 @@ Before doing anything, please ensure that you have: - if using a Retrofit Dynamic Partitions ROM such as ParanoidAndoid -> untoggle `Unmount System before installing a ZIP` in the Settings; - flash the ROM; - flash the kernel; -- **if using Magisk** --> flash Magisk root manager (you must change the `.apk` extension into `.zip` for this); +- **if using Magisk** --> flash Magisk root manager (you can flash the .apk directly, it'll be processed as a ZIP); - flash DM-Verity and Force Encrypt disabler zip; - reboot into system via `Reboot -> System` . @@ -67,7 +67,9 @@ Before doing anything, please ensure that you have: - open NetHunter app (if seeing a Busybox-related error, press "OK" and re-open the app); - navigate to the `Kali Chroot Manager` submenu and install the chroot (if you downloaded it beforehand, use the "restore" option); - make sure that your NetHunter and NetHunter Terminal apps are properly configured to see the installed chroot directory (by default it may be `/data/local/nhsystem/kalifs`; if you see it anywhere, change it to `/data/local/nhsystem/kali-arm64`); -- in NetHunter Terminal app open `Kali` shell (if it opens properly, then congratulations, you have a working Kali NetHunter on your device). +- in NetHunter Terminal app open `Kali` shell (if it opens properly, then congratulations, you have a working Kali NetHunter on your device); +- unlock Developer Options in Settings; +- toggle "Wi-Fi non-persistent MAC randomisation" option or similar. #### For KernelSU users @@ -77,7 +79,9 @@ Before doing anything, please ensure that you have: - open the NetHunter app (if seeing a Busybox-related error, press "OK" and re-open the app); - navigate to the `Kali Chroot Manager` submenu and install the chroot (if you downloaded it beforehand, use the "restore" option); - make sure that your NetHunter and NetHunter Terminal apps are properly configured to see the installed chroot directory (by default it may be `/data/local/nhsystem/kalifs`; if you see it anywhere, change it to `/data/local/nhsystem/kali-arm64`); -- in NetHunter Terminal app open `Kali` shell (if it opens properly, then congratulations, you have a working Kali NetHunter on your device). +- in NetHunter Terminal app open `Kali` shell (if it opens properly, then congratulations, you have a working Kali NetHunter on your device); +- unlock Developer Options in Settings; +- toggle "Wi-Fi non-persistent MAC randomisation" option or similar. #### For x_kernel-based kernel + ParanoidAndroid users From 1cf3d2c3faf53c6dfb20cd3b4dd673d5fbb39f40 Mon Sep 17 00:00:00 2001 From: Joseph Date: Fri, 23 Jan 2026 12:43:33 +0100 Subject: [PATCH 02/19] refactor: improve argument sharing --- zkb/__main__.py | 218 +++++++++++++++++++----------------------------- 1 file changed, 85 insertions(+), 133 deletions(-) diff --git a/zkb/__main__.py b/zkb/__main__.py index 83b13d8..f94411e 100644 --- a/zkb/__main__.py +++ b/zkb/__main__.py @@ -6,6 +6,8 @@ from pathlib import Path from importlib.metadata import version +from pydantic.types import PastDate + from zkb.core import KernelBuilder, AssetsCollector from zkb.tools import cleaning as cm, commands as ccmd, Logger as logger from zkb.configs import ArgumentConfig, DirectoryConfig as dcfg @@ -58,92 +60,92 @@ def parse_args() -> argparse.Namespace: ) parser_parent.add_argument("-v", "--version", action="version", version=__get_version()) - # common argument attributes for subparsers - help_base = "select a kernel base for the build" - help_codename = "select device codename" - help_benv = "select build environment" - help_clean = "remove Docker/Podman image from the host machine after build" - choices_benv = {"local", "docker", "podman"} - choices_base = {"los", "pa", "x", "aosp"} - help_defconfig = "specify path to custom defconfig" - help_ksu = "add KernelSU support" - help_lkv = "select Linux Kernel Version" + # common arguments + common_codename = { + "name_or_flags": ("--codename",), + "config": { + "required": True, + "dest": "codename", + "type": str, + "help": "device codename" + } + } + common_benv = { + "name_or_flags": ("--build-env",), + "config": { + "required": True, + "dest": "build_env", + "type": str, + "choices": {"local", "docker", "podman"}, + "help": "build environment" + } + } + common_base = { + "name_or_flags": ("--base",), + "config": { + "required": True, + "dest": "base", + "type": str, + "choices": {"los", "pa", "x", "aosp"}, + "help": "kernel source base" + } + } + common_defconfig = { + "name_or_flags": ("--defconfig",), + "config": { + "required": False, + "dest": "defconfig", + "type": Path, + "help": "path to custom defconfig" + } + } + common_lkv = { + "name_or_flags": ("--lkv",), + "config": { + "required": True, + "dest": "lkv", + "type": str, + "help": "Linux kernel version" + } + } + common_ksu = { + "name_or_flags": ("--ksu",), + "config": { + "action": "store_true", + "dest": "ksu", + "help": "flag for KernelSU support" + } + } + common_clean_image = { + "name_or_flags": ("--clean-image",), + "config": { + "action": "store_true", + "dest": "clean_image", + "help": "clean Docker cache after the build" + } + } # kernel - parser_kernel.add_argument( - "--build-env", - type=str, - dest="benv", - required=True, - choices=choices_benv, - help=help_benv, - ) - parser_kernel.add_argument( - "--base", - type=str, - required=True, - help=help_base, - choices=choices_base - ) - parser_kernel.add_argument( - "--codename", - type=str, - required=True, - help=help_codename - ) - parser_kernel.add_argument( - "--lkv", - type=str, - required=True, - help=help_lkv - ) + parser_kernel.add_argument(*common_benv["name_or_flags"], **common_benv["config"]) + parser_kernel.add_argument(*common_base["name_or_flags"], **common_base["config"]) + parser_kernel.add_argument(*common_codename["name_or_flags"], **common_codename["config"]) + parser_kernel.add_argument(*common_lkv["name_or_flags"], **common_lkv["config"]) + parser_kernel.add_argument(*common_ksu["name_or_flags"], **common_ksu["config"]) + parser_kernel.add_argument(*common_defconfig["name_or_flags"], **common_defconfig["config"]) + parser_kernel.add_argument(*common_clean_image["name_or_flags"], **common_clean_image["config"]) parser_kernel.add_argument( "-c", "--clean", dest="clean_kernel", action="store_true", help="don't build anything, only clean kernel directories" ) - parser_kernel.add_argument( - "--clean-image", - action="store_true", - dest="clean_image", - help=help_clean - ) - parser_kernel.add_argument( - "--ksu", - action="store_true", - dest="ksu", - help=help_ksu - ) - parser_kernel.add_argument( - "--defconfig", - type=Path, - dest="defconfig", - help=help_defconfig - ) # assets - parser_assets.add_argument( - "--build-env", - type=str, - dest="benv", - required=True, - choices=choices_benv, - help=help_benv - ) - parser_assets.add_argument( - "--base", - type=str, - required=True, - help=help_base, - choices=choices_base - ) - parser_assets.add_argument( - "--codename", - type=str, - required=True, - help=help_codename - ) + parser_assets.add_argument(*common_benv["name_or_flags"], **common_benv["config"]) + parser_assets.add_argument(*common_base["name_or_flags"], **common_base["config"]) + parser_assets.add_argument(*common_codename["name_or_flags"], **common_codename["config"]) + parser_assets.add_argument(*common_ksu["name_or_flags"], **common_ksu["config"]) + parser_assets.add_argument(*common_clean_image["name_or_flags"], **common_clean_image["config"]) parser_assets.add_argument( "--chroot", type=str, @@ -157,53 +159,21 @@ def parse_args() -> argparse.Namespace: action="store_true", help="download only the ROM as an asset" ) - parser_assets.add_argument( - "--clean-image", - action="store_true", - dest="clean_image", - help=help_clean - ) parser_assets.add_argument( "--clean", dest="clean_assets", action="store_true", help="autoclean 'assets' folder if it exists" ) - parser_assets.add_argument( - "--ksu", - action="store_true", - dest="ksu", - help=help_ksu - ) # bundle - parser_bundle.add_argument( - "--build-env", - type=str, - dest="benv", - required=True, - choices=choices_benv, - help=help_benv - ) - parser_bundle.add_argument( - "--base", - type=str, - required=True, - help=help_base, - choices=choices_base - ) - parser_bundle.add_argument( - "--codename", - type=str, - required=True, - help=help_codename - ) - parser_bundle.add_argument( - "--lkv", - type=str, - required=True, - help=help_lkv - ) + parser_bundle.add_argument(*common_benv["name_or_flags"], **common_benv["config"]) + parser_bundle.add_argument(*common_base["name_or_flags"], **common_base["config"]) + parser_bundle.add_argument(*common_codename["name_or_flags"], **common_codename["config"]) + parser_bundle.add_argument(*common_lkv["name_or_flags"], **common_lkv["config"]) + parser_bundle.add_argument(*common_ksu["name_or_flags"], **common_ksu["config"]) + parser_bundle.add_argument(*common_defconfig["name_or_flags"], **common_defconfig["config"]) + parser_bundle.add_argument(*common_clean_image["name_or_flags"], **common_clean_image["config"]) parser_bundle.add_argument( "--package-type", type=str, @@ -218,24 +188,6 @@ def parse_args() -> argparse.Namespace: dest="conan_upload", help="upload Conan packages to remote" ) - parser_bundle.add_argument( - "--clean-image", - action="store_true", - dest="clean_image", - help=help_clean - ) - parser_bundle.add_argument( - "--ksu", - action="store_true", - dest="ksu", - help=help_ksu - ) - parser_bundle.add_argument( - "--defconfig", - type=Path, - dest="defconfig", - help=help_defconfig - ) return parser_parent.parse_args(args) From 74d634fae8db7234f120021a777cc33c9b6b4fe8 Mon Sep 17 00:00:00 2001 From: Joseph Date: Fri, 23 Jan 2026 12:44:12 +0100 Subject: [PATCH 03/19] chore: update dependencies --- requirement-uv.txt | 2 +- uv.lock | 84 +++++++++++++++++++++++----------------------- 2 files changed, 43 insertions(+), 43 deletions(-) diff --git a/requirement-uv.txt b/requirement-uv.txt index 94ee389..8664a39 100644 --- a/requirement-uv.txt +++ b/requirement-uv.txt @@ -1 +1 @@ -uv==0.9.22 +uv==0.9.26 diff --git a/uv.lock b/uv.lock index ca73864..bc03031 100644 --- a/uv.lock +++ b/uv.lock @@ -30,16 +30,16 @@ wheels = [ [[package]] name = "bandit" -version = "1.9.2" +version = "1.9.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pyyaml", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, { name = "rich", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, { name = "stevedore", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/cf/72/f704a97aac430aeb704fa16435dfa24fbeaf087d46724d0965eb1f756a2c/bandit-1.9.2.tar.gz", hash = "sha256:32410415cd93bf9c8b91972159d5cf1e7f063a9146d70345641cd3877de348ce", size = 4241659, upload-time = "2025-11-23T21:36:18.722Z" } +sdist = { url = "https://files.pythonhosted.org/packages/89/76/a7f3e639b78601118aaa4a394db2c66ae2597fbd8c39644c32874ed11e0c/bandit-1.9.3.tar.gz", hash = "sha256:ade4b9b7786f89ef6fc7344a52b34558caec5da74cb90373aed01de88472f774", size = 4242154, upload-time = "2026-01-19T04:05:22.802Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/55/1a/5b0320642cca53a473e79c7d273071b5a9a8578f9e370b74da5daa2768d7/bandit-1.9.2-py3-none-any.whl", hash = "sha256:bda8d68610fc33a6e10b7a8f1d61d92c8f6c004051d5e946406be1fb1b16a868", size = 134377, upload-time = "2025-11-23T21:36:17.39Z" }, + { url = "https://files.pythonhosted.org/packages/e0/0b/8bdc52111c83e2dc2f97403dc87c0830b8989d9ae45732b34b686326fb2c/bandit-1.9.3-py3-none-any.whl", hash = "sha256:4745917c88d2246def79748bde5e08b9d5e9b92f877863d43fab70cd8814ce6a", size = 134451, upload-time = "2026-01-19T04:05:20.938Z" }, ] [[package]] @@ -211,11 +211,11 @@ wheels = [ [[package]] name = "dill" -version = "0.4.0" +version = "0.4.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/12/80/630b4b88364e9a8c8c5797f4602d0f76ef820909ee32f0bacb9f90654042/dill-0.4.0.tar.gz", hash = "sha256:0633f1d2df477324f53a895b02c901fb961bdbf65a17122586ea7019292cbcf0", size = 186976, upload-time = "2025-04-16T00:41:48.867Z" } +sdist = { url = "https://files.pythonhosted.org/packages/81/e1/56027a71e31b02ddc53c7d65b01e68edf64dea2932122fe7746a516f75d5/dill-0.4.1.tar.gz", hash = "sha256:423092df4182177d4d8ba8290c8a5b640c66ab35ec7da59ccfa00f6fa3eea5fa", size = 187315, upload-time = "2026-01-19T02:36:56.85Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/50/3d/9373ad9c56321fdab5b41197068e1d8c25883b3fea29dd361f9b55116869/dill-0.4.0-py3-none-any.whl", hash = "sha256:44f54bf6412c2c8464c14e8243eb163690a9800dbe2c367330883b19c7561049", size = 119668, upload-time = "2025-04-16T00:41:47.671Z" }, + { url = "https://files.pythonhosted.org/packages/1e/77/dc8c558f7593132cf8fefec57c4f60c83b16941c574ac5f619abb3ae7933/dill-0.4.1-py3-none-any.whl", hash = "sha256:1e1ce33e978ae97fcfcff5638477032b801c46c7c65cf717f95fbc2248f79a9d", size = 120019, upload-time = "2026-01-19T02:36:55.663Z" }, ] [[package]] @@ -247,20 +247,20 @@ wheels = [ [[package]] name = "filelock" -version = "3.20.2" +version = "3.20.3" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/c1/e0/a75dbe4bca1e7d41307323dad5ea2efdd95408f74ab2de8bd7dba9b51a1a/filelock-3.20.2.tar.gz", hash = "sha256:a2241ff4ddde2a7cebddf78e39832509cb045d18ec1a09d7248d6bfc6bfbbe64", size = 19510, upload-time = "2026-01-02T15:33:32.582Z" } +sdist = { url = "https://files.pythonhosted.org/packages/1d/65/ce7f1b70157833bf3cb851b556a37d4547ceafc158aa9b34b36782f23696/filelock-3.20.3.tar.gz", hash = "sha256:18c57ee915c7ec61cff0ecf7f0f869936c7c30191bb0cf406f1341778d0834e1", size = 19485, upload-time = "2026-01-09T17:55:05.421Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/9a/30/ab407e2ec752aa541704ed8f93c11e2a5d92c168b8a755d818b74a3c5c2d/filelock-3.20.2-py3-none-any.whl", hash = "sha256:fbba7237d6ea277175a32c54bb71ef814a8546d8601269e1bfc388de333974e8", size = 16697, upload-time = "2026-01-02T15:33:31.133Z" }, + { url = "https://files.pythonhosted.org/packages/b5/36/7fb70f04bf00bc646cd5bb45aa9eddb15e19437a28b8fb2b4a5249fac770/filelock-3.20.3-py3-none-any.whl", hash = "sha256:4b0dda527ee31078689fc205ec4f1c1bf7d56cf88b6dc9426c4f230e46c2dce1", size = 16701, upload-time = "2026-01-09T17:55:04.334Z" }, ] [[package]] name = "identify" -version = "2.6.15" +version = "2.6.16" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ff/e7/685de97986c916a6d93b3876139e00eef26ad5bbbd61925d670ae8013449/identify-2.6.15.tar.gz", hash = "sha256:e4f4864b96c6557ef2a1e1c951771838f4edc9df3a72ec7118b338801b11c7bf", size = 99311, upload-time = "2025-10-02T17:43:40.631Z" } +sdist = { url = "https://files.pythonhosted.org/packages/5b/8d/e8b97e6bd3fb6fb271346f7981362f1e04d6a7463abd0de79e1fda17c067/identify-2.6.16.tar.gz", hash = "sha256:846857203b5511bbe94d5a352a48ef2359532bc8f6727b5544077a0dcfb24980", size = 99360, upload-time = "2026-01-12T18:58:58.201Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/0f/1c/e5fd8f973d4f375adb21565739498e2e9a1e54c858a97b9a8ccfdc81da9b/identify-2.6.15-py2.py3-none-any.whl", hash = "sha256:1181ef7608e00704db228516541eb83a88a9f94433a8c80bb9b5bd54b1d81757", size = 99183, upload-time = "2025-10-02T17:43:39.137Z" }, + { url = "https://files.pythonhosted.org/packages/b8/58/40fbbcefeda82364720eba5cf2270f98496bdfa19ea75b4cccae79c698e6/identify-2.6.16-py2.py3-none-any.whl", hash = "sha256:391ee4d77741d994189522896270b787aed8670389bfd60f326d677d64a6dfb0", size = 99202, upload-time = "2026-01-12T18:58:56.627Z" }, ] [[package]] @@ -400,11 +400,11 @@ wheels = [ [[package]] name = "packaging" -version = "25.0" +version = "26.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a1/d4/1fc4078c65507b51b96ca8f8c3ba19e6a61c8253c72794544580a7b6c24d/packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f", size = 165727, upload-time = "2025-04-19T11:48:59.673Z" } +sdist = { url = "https://files.pythonhosted.org/packages/65/ee/299d360cdc32edc7d2cf530f3accf79c4fca01e96ffc950d8a52213bd8e4/packaging-26.0.tar.gz", hash = "sha256:00243ae351a257117b6a241061796684b084ed1c516a08c48a3f7e147a9d80b4", size = 143416, upload-time = "2026-01-21T20:50:39.064Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469, upload-time = "2025-04-19T11:48:57.875Z" }, + { url = "https://files.pythonhosted.org/packages/b7/b9/c538f279a4e237a006a2c98387d081e9eb060d203d8ed34467cc0f0b9b53/packaging-26.0-py3-none-any.whl", hash = "sha256:b36f1fef9334a5588b4166f8bcd26a14e521f2b55e6b9de3aaa80d3ff7a37529", size = 74366, upload-time = "2026-01-21T20:50:37.788Z" }, ] [[package]] @@ -582,15 +582,15 @@ wheels = [ [[package]] name = "pyright" -version = "1.1.407" +version = "1.1.408" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "nodeenv", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, { name = "typing-extensions", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/a6/1b/0aa08ee42948b61745ac5b5b5ccaec4669e8884b53d31c8ec20b2fcd6b6f/pyright-1.1.407.tar.gz", hash = "sha256:099674dba5c10489832d4a4b2d302636152a9a42d317986c38474c76fe562262", size = 4122872, upload-time = "2025-10-24T23:17:15.145Z" } +sdist = { url = "https://files.pythonhosted.org/packages/74/b2/5db700e52554b8f025faa9c3c624c59f1f6c8841ba81ab97641b54322f16/pyright-1.1.408.tar.gz", hash = "sha256:f28f2321f96852fa50b5829ea492f6adb0e6954568d1caa3f3af3a5f555eb684", size = 4400578, upload-time = "2026-01-08T08:07:38.795Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/dc/93/b69052907d032b00c40cb656d21438ec00b3a471733de137a3f65a49a0a0/pyright-1.1.407-py3-none-any.whl", hash = "sha256:6dd419f54fcc13f03b52285796d65e639786373f433e243f8b94cf93a7444d21", size = 5997008, upload-time = "2025-10-24T23:17:13.159Z" }, + { url = "https://files.pythonhosted.org/packages/0c/82/a2c93e32800940d9573fb28c346772a14778b84ba7524e691b324620ab89/pyright-1.1.408-py3-none-any.whl", hash = "sha256:090b32865f4fdb1e0e6cd82bf5618480d48eecd2eb2e70f960982a3d9a4c17c1", size = 6399144, upload-time = "2026-01-08T08:07:37.082Z" }, ] [[package]] @@ -700,25 +700,25 @@ wheels = [ [[package]] name = "ruff" -version = "0.14.10" +version = "0.14.14" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/57/08/52232a877978dd8f9cf2aeddce3e611b40a63287dfca29b6b8da791f5e8d/ruff-0.14.10.tar.gz", hash = "sha256:9a2e830f075d1a42cd28420d7809ace390832a490ed0966fe373ba288e77aaf4", size = 5859763, upload-time = "2025-12-18T19:28:57.98Z" } +sdist = { url = "https://files.pythonhosted.org/packages/2e/06/f71e3a86b2df0dfa2d2f72195941cd09b44f87711cb7fa5193732cb9a5fc/ruff-0.14.14.tar.gz", hash = "sha256:2d0f819c9a90205f3a867dbbd0be083bee9912e170fd7d9704cc8ae45824896b", size = 4515732, upload-time = "2026-01-22T22:30:17.527Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/60/01/933704d69f3f05ee16ef11406b78881733c186fe14b6a46b05cfcaf6d3b2/ruff-0.14.10-py3-none-linux_armv6l.whl", hash = "sha256:7a3ce585f2ade3e1f29ec1b92df13e3da262178df8c8bdf876f48fa0e8316c49", size = 13527080, upload-time = "2025-12-18T19:29:25.642Z" }, - { url = "https://files.pythonhosted.org/packages/df/58/a0349197a7dfa603ffb7f5b0470391efa79ddc327c1e29c4851e85b09cc5/ruff-0.14.10-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:674f9be9372907f7257c51f1d4fc902cb7cf014b9980152b802794317941f08f", size = 13797320, upload-time = "2025-12-18T19:29:02.571Z" }, - { url = "https://files.pythonhosted.org/packages/7b/82/36be59f00a6082e38c23536df4e71cdbc6af8d7c707eade97fcad5c98235/ruff-0.14.10-py3-none-macosx_11_0_arm64.whl", hash = "sha256:d85713d522348837ef9df8efca33ccb8bd6fcfc86a2cde3ccb4bc9d28a18003d", size = 12918434, upload-time = "2025-12-18T19:28:51.202Z" }, - { url = "https://files.pythonhosted.org/packages/a6/00/45c62a7f7e34da92a25804f813ebe05c88aa9e0c25e5cb5a7d23dd7450e3/ruff-0.14.10-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6987ebe0501ae4f4308d7d24e2d0fe3d7a98430f5adfd0f1fead050a740a3a77", size = 13371961, upload-time = "2025-12-18T19:29:04.991Z" }, - { url = "https://files.pythonhosted.org/packages/40/31/a5906d60f0405f7e57045a70f2d57084a93ca7425f22e1d66904769d1628/ruff-0.14.10-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:16a01dfb7b9e4eee556fbfd5392806b1b8550c9b4a9f6acd3dbe6812b193c70a", size = 13275629, upload-time = "2025-12-18T19:29:21.381Z" }, - { url = "https://files.pythonhosted.org/packages/3e/60/61c0087df21894cf9d928dc04bcd4fb10e8b2e8dca7b1a276ba2155b2002/ruff-0.14.10-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7165d31a925b7a294465fa81be8c12a0e9b60fb02bf177e79067c867e71f8b1f", size = 14029234, upload-time = "2025-12-18T19:29:00.132Z" }, - { url = "https://files.pythonhosted.org/packages/44/84/77d911bee3b92348b6e5dab5a0c898d87084ea03ac5dc708f46d88407def/ruff-0.14.10-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:c561695675b972effb0c0a45db233f2c816ff3da8dcfbe7dfc7eed625f218935", size = 15449890, upload-time = "2025-12-18T19:28:53.573Z" }, - { url = "https://files.pythonhosted.org/packages/e9/36/480206eaefa24a7ec321582dda580443a8f0671fdbf6b1c80e9c3e93a16a/ruff-0.14.10-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4bb98fcbbc61725968893682fd4df8966a34611239c9fd07a1f6a07e7103d08e", size = 15123172, upload-time = "2025-12-18T19:29:23.453Z" }, - { url = "https://files.pythonhosted.org/packages/5c/38/68e414156015ba80cef5473d57919d27dfb62ec804b96180bafdeaf0e090/ruff-0.14.10-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f24b47993a9d8cb858429e97bdf8544c78029f09b520af615c1d261bf827001d", size = 14460260, upload-time = "2025-12-18T19:29:27.808Z" }, - { url = "https://files.pythonhosted.org/packages/b3/19/9e050c0dca8aba824d67cc0db69fb459c28d8cd3f6855b1405b3f29cc91d/ruff-0.14.10-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:59aabd2e2c4fd614d2862e7939c34a532c04f1084476d6833dddef4afab87e9f", size = 14229978, upload-time = "2025-12-18T19:29:11.32Z" }, - { url = "https://files.pythonhosted.org/packages/51/eb/e8dd1dd6e05b9e695aa9dd420f4577debdd0f87a5ff2fedda33c09e9be8c/ruff-0.14.10-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:213db2b2e44be8625002dbea33bb9c60c66ea2c07c084a00d55732689d697a7f", size = 14338036, upload-time = "2025-12-18T19:29:09.184Z" }, - { url = "https://files.pythonhosted.org/packages/6a/12/f3e3a505db7c19303b70af370d137795fcfec136d670d5de5391e295c134/ruff-0.14.10-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:b914c40ab64865a17a9a5b67911d14df72346a634527240039eb3bd650e5979d", size = 13264051, upload-time = "2025-12-18T19:29:13.431Z" }, - { url = "https://files.pythonhosted.org/packages/08/64/8c3a47eaccfef8ac20e0484e68e0772013eb85802f8a9f7603ca751eb166/ruff-0.14.10-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:1484983559f026788e3a5c07c81ef7d1e97c1c78ed03041a18f75df104c45405", size = 13283998, upload-time = "2025-12-18T19:29:06.994Z" }, - { url = "https://files.pythonhosted.org/packages/12/84/534a5506f4074e5cc0529e5cd96cfc01bb480e460c7edf5af70d2bcae55e/ruff-0.14.10-py3-none-musllinux_1_2_i686.whl", hash = "sha256:c70427132db492d25f982fffc8d6c7535cc2fd2c83fc8888f05caaa248521e60", size = 13601891, upload-time = "2025-12-18T19:28:55.811Z" }, - { url = "https://files.pythonhosted.org/packages/0d/1e/14c916087d8598917dbad9b2921d340f7884824ad6e9c55de948a93b106d/ruff-0.14.10-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:5bcf45b681e9f1ee6445d317ce1fa9d6cba9a6049542d1c3d5b5958986be8830", size = 14336660, upload-time = "2025-12-18T19:29:16.531Z" }, + { url = "https://files.pythonhosted.org/packages/d2/89/20a12e97bc6b9f9f68343952da08a8099c57237aef953a56b82711d55edd/ruff-0.14.14-py3-none-linux_armv6l.whl", hash = "sha256:7cfe36b56e8489dee8fbc777c61959f60ec0f1f11817e8f2415f429552846aed", size = 10467650, upload-time = "2026-01-22T22:30:08.578Z" }, + { url = "https://files.pythonhosted.org/packages/a3/b1/c5de3fd2d5a831fcae21beda5e3589c0ba67eec8202e992388e4b17a6040/ruff-0.14.14-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:6006a0082336e7920b9573ef8a7f52eec837add1265cc74e04ea8a4368cd704c", size = 10883245, upload-time = "2026-01-22T22:30:04.155Z" }, + { url = "https://files.pythonhosted.org/packages/b8/7c/3c1db59a10e7490f8f6f8559d1db8636cbb13dccebf18686f4e3c9d7c772/ruff-0.14.14-py3-none-macosx_11_0_arm64.whl", hash = "sha256:026c1d25996818f0bf498636686199d9bd0d9d6341c9c2c3b62e2a0198b758de", size = 10231273, upload-time = "2026-01-22T22:30:34.642Z" }, + { url = "https://files.pythonhosted.org/packages/a1/6e/5e0e0d9674be0f8581d1f5e0f0a04761203affce3232c1a1189d0e3b4dad/ruff-0.14.14-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f666445819d31210b71e0a6d1c01e24447a20b85458eea25a25fe8142210ae0e", size = 10585753, upload-time = "2026-01-22T22:30:31.781Z" }, + { url = "https://files.pythonhosted.org/packages/23/09/754ab09f46ff1884d422dc26d59ba18b4e5d355be147721bb2518aa2a014/ruff-0.14.14-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3c0f18b922c6d2ff9a5e6c3ee16259adc513ca775bcf82c67ebab7cbd9da5bc8", size = 10286052, upload-time = "2026-01-22T22:30:24.827Z" }, + { url = "https://files.pythonhosted.org/packages/c8/cc/e71f88dd2a12afb5f50733851729d6b571a7c3a35bfdb16c3035132675a0/ruff-0.14.14-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1629e67489c2dea43e8658c3dba659edbfd87361624b4040d1df04c9740ae906", size = 11043637, upload-time = "2026-01-22T22:30:13.239Z" }, + { url = "https://files.pythonhosted.org/packages/67/b2/397245026352494497dac935d7f00f1468c03a23a0c5db6ad8fc49ca3fb2/ruff-0.14.14-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:27493a2131ea0f899057d49d303e4292b2cae2bb57253c1ed1f256fbcd1da480", size = 12194761, upload-time = "2026-01-22T22:30:22.542Z" }, + { url = "https://files.pythonhosted.org/packages/5b/06/06ef271459f778323112c51b7587ce85230785cd64e91772034ddb88f200/ruff-0.14.14-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:01ff589aab3f5b539e35db38425da31a57521efd1e4ad1ae08fc34dbe30bd7df", size = 12005701, upload-time = "2026-01-22T22:30:20.499Z" }, + { url = "https://files.pythonhosted.org/packages/41/d6/99364514541cf811ccc5ac44362f88df66373e9fec1b9d1c4cc830593fe7/ruff-0.14.14-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1cc12d74eef0f29f51775f5b755913eb523546b88e2d733e1d701fe65144e89b", size = 11282455, upload-time = "2026-01-22T22:29:59.679Z" }, + { url = "https://files.pythonhosted.org/packages/ca/71/37daa46f89475f8582b7762ecd2722492df26421714a33e72ccc9a84d7a5/ruff-0.14.14-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bb8481604b7a9e75eff53772496201690ce2687067e038b3cc31aaf16aa0b974", size = 11215882, upload-time = "2026-01-22T22:29:57.032Z" }, + { url = "https://files.pythonhosted.org/packages/2c/10/a31f86169ec91c0705e618443ee74ede0bdd94da0a57b28e72db68b2dbac/ruff-0.14.14-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:14649acb1cf7b5d2d283ebd2f58d56b75836ed8c6f329664fa91cdea19e76e66", size = 11180549, upload-time = "2026-01-22T22:30:27.175Z" }, + { url = "https://files.pythonhosted.org/packages/fd/1e/c723f20536b5163adf79bdd10c5f093414293cdf567eed9bdb7b83940f3f/ruff-0.14.14-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:e8058d2145566510790eab4e2fad186002e288dec5e0d343a92fe7b0bc1b3e13", size = 10543416, upload-time = "2026-01-22T22:30:01.964Z" }, + { url = "https://files.pythonhosted.org/packages/3e/34/8a84cea7e42c2d94ba5bde1d7a4fae164d6318f13f933d92da6d7c2041ff/ruff-0.14.14-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:e651e977a79e4c758eb807f0481d673a67ffe53cfa92209781dfa3a996cf8412", size = 10285491, upload-time = "2026-01-22T22:30:29.51Z" }, + { url = "https://files.pythonhosted.org/packages/55/ef/b7c5ea0be82518906c978e365e56a77f8de7678c8bb6651ccfbdc178c29f/ruff-0.14.14-py3-none-musllinux_1_2_i686.whl", hash = "sha256:cc8b22da8d9d6fdd844a68ae937e2a0adf9b16514e9a97cc60355e2d4b219fc3", size = 10733525, upload-time = "2026-01-22T22:30:06.499Z" }, + { url = "https://files.pythonhosted.org/packages/6a/5b/aaf1dfbcc53a2811f6cc0a1759de24e4b03e02ba8762daabd9b6bd8c59e3/ruff-0.14.14-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:16bc890fb4cc9781bb05beb5ab4cd51be9e7cb376bf1dd3580512b24eb3fda2b", size = 11315626, upload-time = "2026-01-22T22:30:36.848Z" }, ] [[package]] @@ -741,11 +741,11 @@ wheels = [ [[package]] name = "tomlkit" -version = "0.13.3" +version = "0.14.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/cc/18/0bbf3884e9eaa38819ebe46a7bd25dcd56b67434402b66a58c4b8e552575/tomlkit-0.13.3.tar.gz", hash = "sha256:430cf247ee57df2b94ee3fbe588e71d362a941ebb545dec29b53961d61add2a1", size = 185207, upload-time = "2025-06-05T07:13:44.947Z" } +sdist = { url = "https://files.pythonhosted.org/packages/c3/af/14b24e41977adb296d6bd1fb59402cf7d60ce364f90c890bd2ec65c43b5a/tomlkit-0.14.0.tar.gz", hash = "sha256:cf00efca415dbd57575befb1f6634c4f42d2d87dbba376128adb42c121b87064", size = 187167, upload-time = "2026-01-13T01:14:53.304Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/bd/75/8539d011f6be8e29f339c42e633aae3cb73bffa95dd0f9adec09b9c58e85/tomlkit-0.13.3-py3-none-any.whl", hash = "sha256:c89c649d79ee40629a9fda55f8ace8c6a1b42deb912b2a8fd8d942ddadb606b0", size = 38901, upload-time = "2025-06-05T07:13:43.546Z" }, + { url = "https://files.pythonhosted.org/packages/b5/11/87d6d29fb5d237229d67973a6c9e06e048f01cf4994dee194ab0ea841814/tomlkit-0.14.0-py3-none-any.whl", hash = "sha256:592064ed85b40fa213469f81ac584f67a4f2992509a7c3ea2d632208623a3680", size = 39310, upload-time = "2026-01-13T01:14:51.965Z" }, ] [[package]] @@ -789,21 +789,21 @@ wheels = [ [[package]] name = "virtualenv" -version = "20.35.4" +version = "20.36.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "distlib", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, { name = "filelock", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, { name = "platformdirs", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/20/28/e6f1a6f655d620846bd9df527390ecc26b3805a0c5989048c210e22c5ca9/virtualenv-20.35.4.tar.gz", hash = "sha256:643d3914d73d3eeb0c552cbb12d7e82adf0e504dbf86a3182f8771a153a1971c", size = 6028799, upload-time = "2025-10-29T06:57:40.511Z" } +sdist = { url = "https://files.pythonhosted.org/packages/aa/a3/4d310fa5f00863544e1d0f4de93bddec248499ccf97d4791bc3122c9d4f3/virtualenv-20.36.1.tar.gz", hash = "sha256:8befb5c81842c641f8ee658481e42641c68b5eab3521d8e092d18320902466ba", size = 6032239, upload-time = "2026-01-09T18:21:01.296Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/79/0c/c05523fa3181fdf0c9c52a6ba91a23fbf3246cc095f26f6516f9c60e6771/virtualenv-20.35.4-py3-none-any.whl", hash = "sha256:c21c9cede36c9753eeade68ba7d523529f228a403463376cf821eaae2b650f1b", size = 6005095, upload-time = "2025-10-29T06:57:37.598Z" }, + { url = "https://files.pythonhosted.org/packages/6a/2a/dc2228b2888f51192c7dc766106cd475f1b768c10caaf9727659726f7391/virtualenv-20.36.1-py3-none-any.whl", hash = "sha256:575a8d6b124ef88f6f51d56d656132389f961062a9177016a50e4f507bbcc19f", size = 6008258, upload-time = "2026-01-09T18:20:59.425Z" }, ] [[package]] name = "zero-kernel-builder" -version = "0.6.4" +version = "0.7.0" source = { editable = "." } [package.dev-dependencies] From fbb3ab5a8a9304b5c9e8a271ff4503051abdc667 Mon Sep 17 00:00:00 2001 From: Joseph Date: Fri, 23 Jan 2026 12:44:52 +0100 Subject: [PATCH 04/19] chore: remove redundant comment --- zkb/tools/logger.py | 1 - 1 file changed, 1 deletion(-) diff --git a/zkb/tools/logger.py b/zkb/tools/logger.py index a51da2b..cf76e64 100644 --- a/zkb/tools/logger.py +++ b/zkb/tools/logger.py @@ -40,7 +40,6 @@ def _init(self, level = logging.DEBUG) -> None: self.logger.propagate = False if not self.logger.handlers: - #formatter = logging.Formatter("[%(asctime)s] [%(levelname).1s] %(message)s") formatter = self._get_coloured_formatter() # direct DEBUG and INFO to stdout; WARNING, ERROR and CRITICAL to stderr From 46bf151211d09e0ea028ddc3689874a9900a7125 Mon Sep 17 00:00:00 2001 From: Joseph Date: Fri, 23 Jan 2026 12:45:15 +0100 Subject: [PATCH 05/19] chore: update project version --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index eee39bd..079f8d0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "zero-kernel-builder" -version = "0.6.4" +version = "0.7.0" description = "Advanced Android kernel builder with Kali NetHunter support." authors = [{name = "seppzer0"}] readme = "README.md" From 688bc9fb1a41bcd4f8f6ffd38fc32ecef6dbb962 Mon Sep 17 00:00:00 2001 From: Joseph Date: Fri, 23 Jan 2026 12:48:37 +0100 Subject: [PATCH 06/19] build: add new asset dependency --- zkb/core/assets_collector.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/zkb/core/assets_collector.py b/zkb/core/assets_collector.py index 62dbf47..9c64fc6 100644 --- a/zkb/core/assets_collector.py +++ b/zkb/core/assets_collector.py @@ -86,6 +86,10 @@ def assets(self) -> list: project="nfcgate/nfcgate", file_filter=".apk" ), + GithubApiClient( + project="ImranR98/Obtainium", + file_filter="app-arm64-v8a-release.apk" + ), # files from direct URLs "https://store.nethunter.com/NetHunter.apk", "https://store.nethunter.com/NetHunterKeX.apk", @@ -93,7 +97,7 @@ def assets(self) -> list: "https://store.nethunter.com/NetHunterTerminal.apk", "https://sourceforge.net/projects/op5-5t/files/Android-12/TWRP/twrp-3.7.0_12-5-dyn-cheeseburger_dumpling.img/download", "https://kali.download/nethunter-images/current/rootfs/kali-nethunter-rootfs-{}-arm64.tar.xz".format(self.chroot), - "https://github.com/mozilla-mobile/firefox-android/releases/download/fenix-v117.1.0/fenix-117.1.0-arm64-v8a.apk", + "https://ftp.mozilla.org/pub/fenix/releases/147.0.1/android/fenix-147.0.1-android-arm64-v8a/fenix-147.0.1.multi.android-arm64-v8a.apk", "https://f-droid.org/F-Droid.apk", ] @@ -115,7 +119,6 @@ def check(self) -> None: if len(os.listdir(dcfg.assets)) != 0: cmsg = f'[ ? ] Found an existing "{dcfg.assets.name}" folder, clean it? [Y/n]: ' ans = input(cmsg).lower() if not self.clean_assets else "y" - match ans: case "y": log.warning("Cleaning 'assets' directory..") @@ -128,7 +131,6 @@ def check(self) -> None: case _: log.error("Invalid option selected.") sys.exit(1) - print("\n", end="") def run(self) -> None: From 04d78c4f137b1052565c5fea2a9052bcb831f056 Mon Sep 17 00:00:00 2001 From: Joseph Date: Sat, 28 Feb 2026 17:25:13 +0100 Subject: [PATCH 07/19] refactor: add enums --- requirement-uv.txt | 2 +- scripts/multi_build.py | 4 +- uv.lock | 245 +++++++++++++++++-------------- zkb/__main__.py | 37 +++-- zkb/clients/github.py | 12 +- zkb/clients/los.py | 3 +- zkb/clients/pa.py | 3 +- zkb/clients/rom_api.py | 7 +- zkb/commands/assets.py | 2 +- zkb/commands/bundle.py | 33 +++-- zkb/commands/kernel.py | 2 +- zkb/configs/argument.py | 43 +++--- zkb/configs/directory.py | 8 +- zkb/core/assets_collector.py | 13 +- zkb/core/kernel_builder.py | 2 +- zkb/engines/generic_container.py | 65 ++++---- zkb/enums.py | 71 +++++++++ zkb/managers/resource.py | 6 +- zkb/tools/cleaning.py | 8 +- zkb/tools/commands.py | 4 +- zkb/tools/fileoperations.py | 12 +- zkb/utils/bridge.py | 20 +-- 22 files changed, 358 insertions(+), 244 deletions(-) create mode 100644 zkb/enums.py diff --git a/requirement-uv.txt b/requirement-uv.txt index 8664a39..2d993c4 100644 --- a/requirement-uv.txt +++ b/requirement-uv.txt @@ -1 +1 @@ -uv==0.9.26 +0.10.7 diff --git a/scripts/multi_build.py b/scripts/multi_build.py index fe3a868..621696e 100644 --- a/scripts/multi_build.py +++ b/scripts/multi_build.py @@ -28,8 +28,8 @@ def parse_args() -> argparse.Namespace: def rmove(src: Path, dst: Path) -> None: """Recursively move files from one directory to another. - :param Path src: Source path. - :param Path dst: Destination path. + :param pathlib.Path src: Source path. + :param pathlib.Path dst: Destination path. :return: None """ # for a directory diff --git a/uv.lock b/uv.lock index bc03031..e8a8078 100644 --- a/uv.lock +++ b/uv.lock @@ -21,25 +21,25 @@ wheels = [ [[package]] name = "astroid" -version = "4.0.3" +version = "4.0.4" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a1/ca/c17d0f83016532a1ad87d1de96837164c99d47a3b6bbba28bd597c25b37a/astroid-4.0.3.tar.gz", hash = "sha256:08d1de40d251cc3dc4a7a12726721d475ac189e4e583d596ece7422bc176bda3", size = 406224, upload-time = "2026-01-03T22:14:26.096Z" } +sdist = { url = "https://files.pythonhosted.org/packages/07/63/0adf26577da5eff6eb7a177876c1cfa213856be9926a000f65c4add9692b/astroid-4.0.4.tar.gz", hash = "sha256:986fed8bcf79fb82c78b18a53352a0b287a73817d6dbcfba3162da36667c49a0", size = 406358, upload-time = "2026-02-07T23:35:07.509Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ce/66/686ac4fc6ef48f5bacde625adac698f41d5316a9753c2b20bb0931c9d4e2/astroid-4.0.3-py3-none-any.whl", hash = "sha256:864a0a34af1bd70e1049ba1e61cee843a7252c826d97825fcee9b2fcbd9e1b14", size = 276443, upload-time = "2026-01-03T22:14:24.412Z" }, + { url = "https://files.pythonhosted.org/packages/b0/cf/1c5f42b110e57bc5502eb80dbc3b03d256926062519224835ef08134f1f9/astroid-4.0.4-py3-none-any.whl", hash = "sha256:52f39653876c7dec3e3afd4c2696920e05c83832b9737afc21928f2d2eb7a753", size = 276445, upload-time = "2026-02-07T23:35:05.344Z" }, ] [[package]] name = "bandit" -version = "1.9.3" +version = "1.9.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pyyaml", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, { name = "rich", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, { name = "stevedore", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/89/76/a7f3e639b78601118aaa4a394db2c66ae2597fbd8c39644c32874ed11e0c/bandit-1.9.3.tar.gz", hash = "sha256:ade4b9b7786f89ef6fc7344a52b34558caec5da74cb90373aed01de88472f774", size = 4242154, upload-time = "2026-01-19T04:05:22.802Z" } +sdist = { url = "https://files.pythonhosted.org/packages/aa/c3/0cb80dfe0f3076e5da7e4c5ad8e57bac6ac357ff4a6406205501cade4965/bandit-1.9.4.tar.gz", hash = "sha256:b589e5de2afe70bd4d53fa0c1da6199f4085af666fde00e8a034f152a52cd628", size = 4242677, upload-time = "2026-02-25T06:44:15.503Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e0/0b/8bdc52111c83e2dc2f97403dc87c0830b8989d9ae45732b34b686326fb2c/bandit-1.9.3-py3-none-any.whl", hash = "sha256:4745917c88d2246def79748bde5e08b9d5e9b92f877863d43fab70cd8814ce6a", size = 134451, upload-time = "2026-01-19T04:05:20.938Z" }, + { url = "https://files.pythonhosted.org/packages/05/a4/a26d5b25671d27e03afb5401a0be5899d94ff8fab6a698b1ac5be3ec29ef/bandit-1.9.4-py3-none-any.whl", hash = "sha256:f89ffa663767f5a0585ea075f01020207e966a9c0f2b9ef56a57c7963a3f6f8e", size = 134741, upload-time = "2026-02-25T06:44:13.694Z" }, ] [[package]] @@ -53,11 +53,11 @@ wheels = [ [[package]] name = "certifi" -version = "2026.1.4" +version = "2026.2.25" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e0/2d/a891ca51311197f6ad14a7ef42e2399f36cf2f9bd44752b3dc4eab60fdc5/certifi-2026.1.4.tar.gz", hash = "sha256:ac726dd470482006e014ad384921ed6438c457018f4b3d204aea4281258b2120", size = 154268, upload-time = "2026-01-04T02:42:41.825Z" } +sdist = { url = "https://files.pythonhosted.org/packages/af/2d/7bf41579a8986e348fa033a31cdd0e4121114f6bce2457e8876010b092dd/certifi-2026.2.25.tar.gz", hash = "sha256:e887ab5cee78ea814d3472169153c2d12cd43b14bd03329a39a9c6e2e80bfba7", size = 155029, upload-time = "2026-02-25T02:54:17.342Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e6/ad/3cc14f097111b4de0040c83a525973216457bbeeb63739ef1ed275c1c021/certifi-2026.1.4-py3-none-any.whl", hash = "sha256:9943707519e4add1115f44c2bc244f782c0249876bf51b6599fee1ffbedd685c", size = 152900, upload-time = "2026-01-04T02:42:40.15Z" }, + { url = "https://files.pythonhosted.org/packages/9a/3c/c17fb3ca2d9c3acff52e30b309f538586f9f5b9c9cf454f3845fc9af4881/certifi-2026.2.25-py3-none-any.whl", hash = "sha256:027692e4402ad994f1c42e52a4997a9763c646b73e4096e4d5d6db8af1d6f0fa", size = 153684, upload-time = "2026-02-25T02:54:15.766Z" }, ] [[package]] @@ -152,61 +152,71 @@ sdist = { url = "https://files.pythonhosted.org/packages/ee/e8/0893952ee0c0f7810 [[package]] name = "coverage" -version = "7.13.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/23/f9/e92df5e07f3fc8d4c7f9a0f146ef75446bf870351cd37b788cf5897f8079/coverage-7.13.1.tar.gz", hash = "sha256:b7593fe7eb5feaa3fbb461ac79aac9f9fc0387a5ca8080b0c6fe2ca27b091afd", size = 825862, upload-time = "2025-12-28T15:42:56.969Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/ce/8a/87af46cccdfa78f53db747b09f5f9a21d5fc38d796834adac09b30a8ce74/coverage-7.13.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6f34591000f06e62085b1865c9bc5f7858df748834662a51edadfd2c3bfe0dd3", size = 218927, upload-time = "2025-12-28T15:40:52.814Z" }, - { url = "https://files.pythonhosted.org/packages/82/a8/6e22fdc67242a4a5a153f9438d05944553121c8f4ba70cb072af4c41362e/coverage-7.13.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b67e47c5595b9224599016e333f5ec25392597a89d5744658f837d204e16c63e", size = 219288, upload-time = "2025-12-28T15:40:54.262Z" }, - { url = "https://files.pythonhosted.org/packages/d0/0a/853a76e03b0f7c4375e2ca025df45c918beb367f3e20a0a8e91967f6e96c/coverage-7.13.1-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3e7b8bd70c48ffb28461ebe092c2345536fb18bbbf19d287c8913699735f505c", size = 250786, upload-time = "2025-12-28T15:40:56.059Z" }, - { url = "https://files.pythonhosted.org/packages/ea/b4/694159c15c52b9f7ec7adf49d50e5f8ee71d3e9ef38adb4445d13dd56c20/coverage-7.13.1-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:c223d078112e90dc0e5c4e35b98b9584164bea9fbbd221c0b21c5241f6d51b62", size = 253543, upload-time = "2025-12-28T15:40:57.585Z" }, - { url = "https://files.pythonhosted.org/packages/96/b2/7f1f0437a5c855f87e17cf5d0dc35920b6440ff2b58b1ba9788c059c26c8/coverage-7.13.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:794f7c05af0763b1bbd1b9e6eff0e52ad068be3b12cd96c87de037b01390c968", size = 254635, upload-time = "2025-12-28T15:40:59.443Z" }, - { url = "https://files.pythonhosted.org/packages/e9/d1/73c3fdb8d7d3bddd9473c9c6a2e0682f09fc3dfbcb9c3f36412a7368bcab/coverage-7.13.1-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0642eae483cc8c2902e4af7298bf886d605e80f26382124cddc3967c2a3df09e", size = 251202, upload-time = "2025-12-28T15:41:01.328Z" }, - { url = "https://files.pythonhosted.org/packages/66/3c/f0edf75dcc152f145d5598329e864bbbe04ab78660fe3e8e395f9fff010f/coverage-7.13.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9f5e772ed5fef25b3de9f2008fe67b92d46831bd2bc5bdc5dd6bfd06b83b316f", size = 252566, upload-time = "2025-12-28T15:41:03.319Z" }, - { url = "https://files.pythonhosted.org/packages/17/b3/e64206d3c5f7dcbceafd14941345a754d3dbc78a823a6ed526e23b9cdaab/coverage-7.13.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:45980ea19277dc0a579e432aef6a504fe098ef3a9032ead15e446eb0f1191aee", size = 250711, upload-time = "2025-12-28T15:41:06.411Z" }, - { url = "https://files.pythonhosted.org/packages/dc/ad/28a3eb970a8ef5b479ee7f0c484a19c34e277479a5b70269dc652b730733/coverage-7.13.1-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:e4f18eca6028ffa62adbd185a8f1e1dd242f2e68164dba5c2b74a5204850b4cf", size = 250278, upload-time = "2025-12-28T15:41:08.285Z" }, - { url = "https://files.pythonhosted.org/packages/54/e3/c8f0f1a93133e3e1291ca76cbb63565bd4b5c5df63b141f539d747fff348/coverage-7.13.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f8dca5590fec7a89ed6826fce625595279e586ead52e9e958d3237821fbc750c", size = 252154, upload-time = "2025-12-28T15:41:09.969Z" }, - { url = "https://files.pythonhosted.org/packages/a3/a4/e98e689347a1ff1a7f67932ab535cef82eb5e78f32a9e4132e114bbb3a0a/coverage-7.13.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:cb237bfd0ef4d5eb6a19e29f9e528ac67ac3be932ea6b44fb6cc09b9f3ecff78", size = 218951, upload-time = "2025-12-28T15:41:16.653Z" }, - { url = "https://files.pythonhosted.org/packages/32/33/7cbfe2bdc6e2f03d6b240d23dc45fdaf3fd270aaf2d640be77b7f16989ab/coverage-7.13.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1dcb645d7e34dcbcc96cd7c132b1fc55c39263ca62eb961c064eb3928997363b", size = 219325, upload-time = "2025-12-28T15:41:18.609Z" }, - { url = "https://files.pythonhosted.org/packages/59/f6/efdabdb4929487baeb7cb2a9f7dac457d9356f6ad1b255be283d58b16316/coverage-7.13.1-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3d42df8201e00384736f0df9be2ced39324c3907607d17d50d50116c989d84cd", size = 250309, upload-time = "2025-12-28T15:41:20.629Z" }, - { url = "https://files.pythonhosted.org/packages/12/da/91a52516e9d5aea87d32d1523f9cdcf7a35a3b298e6be05d6509ba3cfab2/coverage-7.13.1-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:fa3edde1aa8807de1d05934982416cb3ec46d1d4d91e280bcce7cca01c507992", size = 252907, upload-time = "2025-12-28T15:41:22.257Z" }, - { url = "https://files.pythonhosted.org/packages/75/38/f1ea837e3dc1231e086db1638947e00d264e7e8c41aa8ecacf6e1e0c05f4/coverage-7.13.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9edd0e01a343766add6817bc448408858ba6b489039eaaa2018474e4001651a4", size = 254148, upload-time = "2025-12-28T15:41:23.87Z" }, - { url = "https://files.pythonhosted.org/packages/7f/43/f4f16b881aaa34954ba446318dea6b9ed5405dd725dd8daac2358eda869a/coverage-7.13.1-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:985b7836931d033570b94c94713c6dba5f9d3ff26045f72c3e5dbc5fe3361e5a", size = 250515, upload-time = "2025-12-28T15:41:25.437Z" }, - { url = "https://files.pythonhosted.org/packages/84/34/8cba7f00078bd468ea914134e0144263194ce849ec3baad187ffb6203d1c/coverage-7.13.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ffed1e4980889765c84a5d1a566159e363b71d6b6fbaf0bebc9d3c30bc016766", size = 252292, upload-time = "2025-12-28T15:41:28.459Z" }, - { url = "https://files.pythonhosted.org/packages/8c/a4/cffac66c7652d84ee4ac52d3ccb94c015687d3b513f9db04bfcac2ac800d/coverage-7.13.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:8842af7f175078456b8b17f1b73a0d16a65dcbdc653ecefeb00a56b3c8c298c4", size = 250242, upload-time = "2025-12-28T15:41:30.02Z" }, - { url = "https://files.pythonhosted.org/packages/f4/78/9a64d462263dde416f3c0067efade7b52b52796f489b1037a95b0dc389c9/coverage-7.13.1-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:ccd7a6fca48ca9c131d9b0a2972a581e28b13416fc313fb98b6d24a03ce9a398", size = 250068, upload-time = "2025-12-28T15:41:32.007Z" }, - { url = "https://files.pythonhosted.org/packages/69/c8/a8994f5fece06db7c4a97c8fc1973684e178599b42e66280dded0524ef00/coverage-7.13.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:0403f647055de2609be776965108447deb8e384fe4a553c119e3ff6bfbab4784", size = 251846, upload-time = "2025-12-28T15:41:33.946Z" }, - { url = "https://files.pythonhosted.org/packages/70/52/f2be52cc445ff75ea8397948c96c1b4ee14f7f9086ea62fc929c5ae7b717/coverage-7.13.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:67170979de0dacac3f3097d02b0ad188d8edcea44ccc44aaa0550af49150c7dc", size = 219643, upload-time = "2025-12-28T15:41:41.567Z" }, - { url = "https://files.pythonhosted.org/packages/47/79/c85e378eaa239e2edec0c5523f71542c7793fe3340954eafb0bc3904d32d/coverage-7.13.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:f80e2bb21bfab56ed7405c2d79d34b5dc0bc96c2c1d2a067b643a09fb756c43a", size = 219997, upload-time = "2025-12-28T15:41:43.418Z" }, - { url = "https://files.pythonhosted.org/packages/fe/9b/b1ade8bfb653c0bbce2d6d6e90cc6c254cbb99b7248531cc76253cb4da6d/coverage-7.13.1-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:f83351e0f7dcdb14d7326c3d8d8c4e915fa685cbfdc6281f9470d97a04e9dfe4", size = 261296, upload-time = "2025-12-28T15:41:45.207Z" }, - { url = "https://files.pythonhosted.org/packages/1f/af/ebf91e3e1a2473d523e87e87fd8581e0aa08741b96265730e2d79ce78d8d/coverage-7.13.1-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:bb3f6562e89bad0110afbe64e485aac2462efdce6232cdec7862a095dc3412f6", size = 263363, upload-time = "2025-12-28T15:41:47.163Z" }, - { url = "https://files.pythonhosted.org/packages/c4/8b/fb2423526d446596624ac7fde12ea4262e66f86f5120114c3cfd0bb2befa/coverage-7.13.1-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:77545b5dcda13b70f872c3b5974ac64c21d05e65b1590b441c8560115dc3a0d1", size = 265783, upload-time = "2025-12-28T15:41:49.03Z" }, - { url = "https://files.pythonhosted.org/packages/9b/26/ef2adb1e22674913b89f0fe7490ecadcef4a71fa96f5ced90c60ec358789/coverage-7.13.1-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a4d240d260a1aed814790bbe1f10a5ff31ce6c21bc78f0da4a1e8268d6c80dbd", size = 260508, upload-time = "2025-12-28T15:41:51.035Z" }, - { url = "https://files.pythonhosted.org/packages/ce/7d/f0f59b3404caf662e7b5346247883887687c074ce67ba453ea08c612b1d5/coverage-7.13.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:d2287ac9360dec3837bfdad969963a5d073a09a85d898bd86bea82aa8876ef3c", size = 263357, upload-time = "2025-12-28T15:41:52.631Z" }, - { url = "https://files.pythonhosted.org/packages/1a/b1/29896492b0b1a047604d35d6fa804f12818fa30cdad660763a5f3159e158/coverage-7.13.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:0d2c11f3ea4db66b5cbded23b20185c35066892c67d80ec4be4bab257b9ad1e0", size = 260978, upload-time = "2025-12-28T15:41:54.589Z" }, - { url = "https://files.pythonhosted.org/packages/48/f2/971de1238a62e6f0a4128d37adadc8bb882ee96afbe03ff1570291754629/coverage-7.13.1-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:3fc6a169517ca0d7ca6846c3c5392ef2b9e38896f61d615cb75b9e7134d4ee1e", size = 259877, upload-time = "2025-12-28T15:41:56.263Z" }, - { url = "https://files.pythonhosted.org/packages/6a/fc/0474efcbb590ff8628830e9aaec5f1831594874360e3251f1fdec31d07a3/coverage-7.13.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:d10a2ed46386e850bb3de503a54f9fe8192e5917fcbb143bfef653a9355e9a53", size = 262069, upload-time = "2025-12-28T15:41:58.093Z" }, - { url = "https://files.pythonhosted.org/packages/aa/8e/ba0e597560c6563fc0adb902fda6526df5d4aa73bb10adf0574d03bd2206/coverage-7.13.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:97ab3647280d458a1f9adb85244e81587505a43c0c7cff851f5116cd2814b894", size = 218996, upload-time = "2025-12-28T15:42:04.978Z" }, - { url = "https://files.pythonhosted.org/packages/6b/8e/764c6e116f4221dc7aa26c4061181ff92edb9c799adae6433d18eeba7a14/coverage-7.13.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:8f572d989142e0908e6acf57ad1b9b86989ff057c006d13b76c146ec6a20216a", size = 219326, upload-time = "2025-12-28T15:42:06.691Z" }, - { url = "https://files.pythonhosted.org/packages/4f/a6/6130dc6d8da28cdcbb0f2bf8865aeca9b157622f7c0031e48c6cf9a0e591/coverage-7.13.1-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:d72140ccf8a147e94274024ff6fd8fb7811354cf7ef88b1f0a988ebaa5bc774f", size = 250374, upload-time = "2025-12-28T15:42:08.786Z" }, - { url = "https://files.pythonhosted.org/packages/82/2b/783ded568f7cd6b677762f780ad338bf4b4750205860c17c25f7c708995e/coverage-7.13.1-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:d3c9f051b028810f5a87c88e5d6e9af3c0ff32ef62763bf15d29f740453ca909", size = 252882, upload-time = "2025-12-28T15:42:10.515Z" }, - { url = "https://files.pythonhosted.org/packages/cd/b2/9808766d082e6a4d59eb0cc881a57fc1600eb2c5882813eefff8254f71b5/coverage-7.13.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f398ba4df52d30b1763f62eed9de5620dcde96e6f491f4c62686736b155aa6e4", size = 254218, upload-time = "2025-12-28T15:42:12.208Z" }, - { url = "https://files.pythonhosted.org/packages/44/ea/52a985bb447c871cb4d2e376e401116520991b597c85afdde1ea9ef54f2c/coverage-7.13.1-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:132718176cc723026d201e347f800cd1a9e4b62ccd3f82476950834dad501c75", size = 250391, upload-time = "2025-12-28T15:42:14.21Z" }, - { url = "https://files.pythonhosted.org/packages/7f/1d/125b36cc12310718873cfc8209ecfbc1008f14f4f5fa0662aa608e579353/coverage-7.13.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:9e549d642426e3579b3f4b92d0431543b012dcb6e825c91619d4e93b7363c3f9", size = 252239, upload-time = "2025-12-28T15:42:16.292Z" }, - { url = "https://files.pythonhosted.org/packages/6a/16/10c1c164950cade470107f9f14bbac8485f8fb8515f515fca53d337e4a7f/coverage-7.13.1-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:90480b2134999301eea795b3a9dbf606c6fbab1b489150c501da84a959442465", size = 250196, upload-time = "2025-12-28T15:42:18.54Z" }, - { url = "https://files.pythonhosted.org/packages/2a/c6/cd860fac08780c6fd659732f6ced1b40b79c35977c1356344e44d72ba6c4/coverage-7.13.1-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:e825dbb7f84dfa24663dd75835e7257f8882629fc11f03ecf77d84a75134b864", size = 250008, upload-time = "2025-12-28T15:42:20.365Z" }, - { url = "https://files.pythonhosted.org/packages/f0/3a/a8c58d3d38f82a5711e1e0a67268362af48e1a03df27c03072ac30feefcf/coverage-7.13.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:623dcc6d7a7ba450bbdbeedbaa0c42b329bdae16491af2282f12a7e809be7eb9", size = 251671, upload-time = "2025-12-28T15:42:22.114Z" }, - { url = "https://files.pythonhosted.org/packages/16/61/d5b7a0a0e0e40d62e59bc8c7aa1afbd86280d82728ba97f0673b746b78e2/coverage-7.13.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:60cfb538fe9ef86e5b2ab0ca8fc8d62524777f6c611dcaf76dc16fbe9b8e698a", size = 219730, upload-time = "2025-12-28T15:42:29.306Z" }, - { url = "https://files.pythonhosted.org/packages/a3/2c/8881326445fd071bb49514d1ce97d18a46a980712b51fee84f9ab42845b4/coverage-7.13.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:57dfc8048c72ba48a8c45e188d811e5efd7e49b387effc8fb17e97936dde5bf6", size = 220001, upload-time = "2025-12-28T15:42:31.319Z" }, - { url = "https://files.pythonhosted.org/packages/b5/d7/50de63af51dfa3a7f91cc37ad8fcc1e244b734232fbc8b9ab0f3c834a5cd/coverage-7.13.1-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3f2f725aa3e909b3c5fdb8192490bdd8e1495e85906af74fe6e34a2a77ba0673", size = 261370, upload-time = "2025-12-28T15:42:32.992Z" }, - { url = "https://files.pythonhosted.org/packages/e1/2c/d31722f0ec918fd7453b2758312729f645978d212b410cd0f7c2aed88a94/coverage-7.13.1-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:9ee68b21909686eeb21dfcba2c3b81fee70dcf38b140dcd5aa70680995fa3aa5", size = 263485, upload-time = "2025-12-28T15:42:34.759Z" }, - { url = "https://files.pythonhosted.org/packages/fa/7a/2c114fa5c5fc08ba0777e4aec4c97e0b4a1afcb69c75f1f54cff78b073ab/coverage-7.13.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:724b1b270cb13ea2e6503476e34541a0b1f62280bc997eab443f87790202033d", size = 265890, upload-time = "2025-12-28T15:42:36.517Z" }, - { url = "https://files.pythonhosted.org/packages/65/d9/f0794aa1c74ceabc780fe17f6c338456bbc4e96bd950f2e969f48ac6fb20/coverage-7.13.1-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:916abf1ac5cf7eb16bc540a5bf75c71c43a676f5c52fcb9fe75a2bd75fb944e8", size = 260445, upload-time = "2025-12-28T15:42:38.646Z" }, - { url = "https://files.pythonhosted.org/packages/49/23/184b22a00d9bb97488863ced9454068c79e413cb23f472da6cbddc6cfc52/coverage-7.13.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:776483fd35b58d8afe3acbd9988d5de592ab6da2d2a865edfdbc9fdb43e7c486", size = 263357, upload-time = "2025-12-28T15:42:40.788Z" }, - { url = "https://files.pythonhosted.org/packages/7d/bd/58af54c0c9199ea4190284f389005779d7daf7bf3ce40dcd2d2b2f96da69/coverage-7.13.1-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:b6f3b96617e9852703f5b633ea01315ca45c77e879584f283c44127f0f1ec564", size = 260959, upload-time = "2025-12-28T15:42:42.808Z" }, - { url = "https://files.pythonhosted.org/packages/4b/2a/6839294e8f78a4891bf1df79d69c536880ba2f970d0ff09e7513d6e352e9/coverage-7.13.1-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:bd63e7b74661fed317212fab774e2a648bc4bb09b35f25474f8e3325d2945cd7", size = 259792, upload-time = "2025-12-28T15:42:44.818Z" }, - { url = "https://files.pythonhosted.org/packages/ba/c3/528674d4623283310ad676c5af7414b9850ab6d55c2300e8aa4b945ec554/coverage-7.13.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:933082f161bbb3e9f90d00990dc956120f608cdbcaeea15c4d897f56ef4fe416", size = 262123, upload-time = "2025-12-28T15:42:47.108Z" }, - { url = "https://files.pythonhosted.org/packages/cc/48/d9f421cb8da5afaa1a64570d9989e00fb7955e6acddc5a12979f7666ef60/coverage-7.13.1-py3-none-any.whl", hash = "sha256:2016745cb3ba554469d02819d78958b571792bb68e31302610e898f80dd3a573", size = 210722, upload-time = "2025-12-28T15:42:54.901Z" }, +version = "7.13.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/24/56/95b7e30fa389756cb56630faa728da46a27b8c6eb46f9d557c68fff12b65/coverage-7.13.4.tar.gz", hash = "sha256:e5c8f6ed1e61a8b2dcdf31eb0b9bbf0130750ca79c1c49eb898e2ad86f5ccc91", size = 827239, upload-time = "2026-02-09T12:59:03.86Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/81/4ce2fdd909c5a0ed1f6dedb88aa57ab79b6d1fbd9b588c1ac7ef45659566/coverage-7.13.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:02231499b08dabbe2b96612993e5fc34217cdae907a51b906ac7fca8027a4459", size = 219449, upload-time = "2026-02-09T12:56:54.889Z" }, + { url = "https://files.pythonhosted.org/packages/5d/96/5238b1efc5922ddbdc9b0db9243152c09777804fb7c02ad1741eb18a11c0/coverage-7.13.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40aa8808140e55dc022b15d8aa7f651b6b3d68b365ea0398f1441e0b04d859c3", size = 219810, upload-time = "2026-02-09T12:56:56.33Z" }, + { url = "https://files.pythonhosted.org/packages/78/72/2f372b726d433c9c35e56377cf1d513b4c16fe51841060d826b95caacec1/coverage-7.13.4-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:5b856a8ccf749480024ff3bd7310adaef57bf31fd17e1bfc404b7940b6986634", size = 251308, upload-time = "2026-02-09T12:56:57.858Z" }, + { url = "https://files.pythonhosted.org/packages/5d/a0/2ea570925524ef4e00bb6c82649f5682a77fac5ab910a65c9284de422600/coverage-7.13.4-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:2c048ea43875fbf8b45d476ad79f179809c590ec7b79e2035c662e7afa3192e3", size = 254052, upload-time = "2026-02-09T12:56:59.754Z" }, + { url = "https://files.pythonhosted.org/packages/e8/ac/45dc2e19a1939098d783c846e130b8f862fbb50d09e0af663988f2f21973/coverage-7.13.4-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b7b38448866e83176e28086674fe7368ab8590e4610fb662b44e345b86d63ffa", size = 255165, upload-time = "2026-02-09T12:57:01.287Z" }, + { url = "https://files.pythonhosted.org/packages/2d/4d/26d236ff35abc3b5e63540d3386e4c3b192168c1d96da5cb2f43c640970f/coverage-7.13.4-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:de6defc1c9badbf8b9e67ae90fd00519186d6ab64e5cc5f3d21359c2a9b2c1d3", size = 257432, upload-time = "2026-02-09T12:57:02.637Z" }, + { url = "https://files.pythonhosted.org/packages/ec/55/14a966c757d1348b2e19caf699415a2a4c4f7feaa4bbc6326a51f5c7dd1b/coverage-7.13.4-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:7eda778067ad7ffccd23ecffce537dface96212576a07924cbf0d8799d2ded5a", size = 251716, upload-time = "2026-02-09T12:57:04.056Z" }, + { url = "https://files.pythonhosted.org/packages/77/33/50116647905837c66d28b2af1321b845d5f5d19be9655cb84d4a0ea806b4/coverage-7.13.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e87f6c587c3f34356c3759f0420693e35e7eb0e2e41e4c011cb6ec6ecbbf1db7", size = 253089, upload-time = "2026-02-09T12:57:05.503Z" }, + { url = "https://files.pythonhosted.org/packages/c2/b4/8efb11a46e3665d92635a56e4f2d4529de6d33f2cb38afd47d779d15fc99/coverage-7.13.4-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:8248977c2e33aecb2ced42fef99f2d319e9904a36e55a8a68b69207fb7e43edc", size = 251232, upload-time = "2026-02-09T12:57:06.879Z" }, + { url = "https://files.pythonhosted.org/packages/51/24/8cd73dd399b812cc76bb0ac260e671c4163093441847ffe058ac9fda1e32/coverage-7.13.4-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:25381386e80ae727608e662474db537d4df1ecd42379b5ba33c84633a2b36d47", size = 255299, upload-time = "2026-02-09T12:57:08.245Z" }, + { url = "https://files.pythonhosted.org/packages/03/94/0a4b12f1d0e029ce1ccc1c800944a9984cbe7d678e470bb6d3c6bc38a0da/coverage-7.13.4-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:ee756f00726693e5ba94d6df2bdfd64d4852d23b09bb0bc700e3b30e6f333985", size = 250796, upload-time = "2026-02-09T12:57:10.142Z" }, + { url = "https://files.pythonhosted.org/packages/73/44/6002fbf88f6698ca034360ce474c406be6d5a985b3fdb3401128031eef6b/coverage-7.13.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fdfc1e28e7c7cdce44985b3043bc13bbd9c747520f94a4d7164af8260b3d91f0", size = 252673, upload-time = "2026-02-09T12:57:12.197Z" }, + { url = "https://files.pythonhosted.org/packages/db/23/aad45061a31677d68e47499197a131eea55da4875d16c1f42021ab963503/coverage-7.13.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b66a2da594b6068b48b2692f043f35d4d3693fb639d5ea8b39533c2ad9ac3ab9", size = 219474, upload-time = "2026-02-09T12:57:19.332Z" }, + { url = "https://files.pythonhosted.org/packages/a5/70/9b8b67a0945f3dfec1fd896c5cefb7c19d5a3a6d74630b99a895170999ae/coverage-7.13.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:3599eb3992d814d23b35c536c28df1a882caa950f8f507cef23d1cbf334995ac", size = 219844, upload-time = "2026-02-09T12:57:20.66Z" }, + { url = "https://files.pythonhosted.org/packages/97/fd/7e859f8fab324cef6c4ad7cff156ca7c489fef9179d5749b0c8d321281c2/coverage-7.13.4-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:93550784d9281e374fb5a12bf1324cc8a963fd63b2d2f223503ef0fd4aa339ea", size = 250832, upload-time = "2026-02-09T12:57:22.007Z" }, + { url = "https://files.pythonhosted.org/packages/e4/dc/b2442d10020c2f52617828862d8b6ee337859cd8f3a1f13d607dddda9cf7/coverage-7.13.4-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:b720ce6a88a2755f7c697c23268ddc47a571b88052e6b155224347389fdf6a3b", size = 253434, upload-time = "2026-02-09T12:57:23.339Z" }, + { url = "https://files.pythonhosted.org/packages/5a/88/6728a7ad17428b18d836540630487231f5470fb82454871149502f5e5aa2/coverage-7.13.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7b322db1284a2ed3aa28ffd8ebe3db91c929b7a333c0820abec3d838ef5b3525", size = 254676, upload-time = "2026-02-09T12:57:24.774Z" }, + { url = "https://files.pythonhosted.org/packages/7c/bc/21244b1b8cedf0dff0a2b53b208015fe798d5f2a8d5348dbfece04224fff/coverage-7.13.4-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f4594c67d8a7c89cf922d9df0438c7c7bb022ad506eddb0fdb2863359ff78242", size = 256807, upload-time = "2026-02-09T12:57:26.125Z" }, + { url = "https://files.pythonhosted.org/packages/97/a0/ddba7ed3251cff51006737a727d84e05b61517d1784a9988a846ba508877/coverage-7.13.4-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:53d133df809c743eb8bce33b24bcababb371f4441340578cd406e084d94a6148", size = 251058, upload-time = "2026-02-09T12:57:27.614Z" }, + { url = "https://files.pythonhosted.org/packages/9b/55/e289addf7ff54d3a540526f33751951bf0878f3809b47f6dfb3def69c6f7/coverage-7.13.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:76451d1978b95ba6507a039090ba076105c87cc76fc3efd5d35d72093964d49a", size = 252805, upload-time = "2026-02-09T12:57:29.066Z" }, + { url = "https://files.pythonhosted.org/packages/13/4e/cc276b1fa4a59be56d96f1dabddbdc30f4ba22e3b1cd42504c37b3313255/coverage-7.13.4-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:7f57b33491e281e962021de110b451ab8a24182589be17e12a22c79047935e23", size = 250766, upload-time = "2026-02-09T12:57:30.522Z" }, + { url = "https://files.pythonhosted.org/packages/94/44/1093b8f93018f8b41a8cf29636c9292502f05e4a113d4d107d14a3acd044/coverage-7.13.4-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:1731dc33dc276dafc410a885cbf5992f1ff171393e48a21453b78727d090de80", size = 254923, upload-time = "2026-02-09T12:57:31.946Z" }, + { url = "https://files.pythonhosted.org/packages/8b/55/ea2796da2d42257f37dbea1aab239ba9263b31bd91d5527cdd6db5efe174/coverage-7.13.4-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:bd60d4fe2f6fa7dff9223ca1bbc9f05d2b6697bc5961072e5d3b952d46e1b1ea", size = 250591, upload-time = "2026-02-09T12:57:33.842Z" }, + { url = "https://files.pythonhosted.org/packages/d4/fa/7c4bb72aacf8af5020675aa633e59c1fbe296d22aed191b6a5b711eb2bc7/coverage-7.13.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9181a3ccead280b828fae232df12b16652702b49d41e99d657f46cc7b1f6ec7a", size = 252364, upload-time = "2026-02-09T12:57:35.743Z" }, + { url = "https://files.pythonhosted.org/packages/52/57/ee93ced533bcb3e6df961c0c6e42da2fc6addae53fb95b94a89b1e33ebd7/coverage-7.13.4-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:40d74da8e6c4b9ac18b15331c4b5ebc35a17069410cad462ad4f40dcd2d50c0d", size = 220165, upload-time = "2026-02-09T12:57:41.639Z" }, + { url = "https://files.pythonhosted.org/packages/c5/e0/969fc285a6fbdda49d91af278488d904dcd7651b2693872f0ff94e40e84a/coverage-7.13.4-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:4223b4230a376138939a9173f1bdd6521994f2aff8047fae100d6d94d50c5a12", size = 220516, upload-time = "2026-02-09T12:57:44.215Z" }, + { url = "https://files.pythonhosted.org/packages/b1/b8/9531944e16267e2735a30a9641ff49671f07e8138ecf1ca13db9fd2560c7/coverage-7.13.4-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:1d4be36a5114c499f9f1f9195e95ebf979460dbe2d88e6816ea202010ba1c34b", size = 261804, upload-time = "2026-02-09T12:57:45.989Z" }, + { url = "https://files.pythonhosted.org/packages/8a/f3/e63df6d500314a2a60390d1989240d5f27318a7a68fa30ad3806e2a9323e/coverage-7.13.4-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:200dea7d1e8095cc6e98cdabe3fd1d21ab17d3cee6dab00cadbb2fe35d9c15b9", size = 263885, upload-time = "2026-02-09T12:57:47.42Z" }, + { url = "https://files.pythonhosted.org/packages/f3/67/7654810de580e14b37670b60a09c599fa348e48312db5b216d730857ffe6/coverage-7.13.4-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b8eb931ee8e6d8243e253e5ed7336deea6904369d2fd8ae6e43f68abbf167092", size = 266308, upload-time = "2026-02-09T12:57:49.345Z" }, + { url = "https://files.pythonhosted.org/packages/37/6f/39d41eca0eab3cc82115953ad41c4e77935286c930e8fad15eaed1389d83/coverage-7.13.4-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:75eab1ebe4f2f64d9509b984f9314d4aa788540368218b858dad56dc8f3e5eb9", size = 267452, upload-time = "2026-02-09T12:57:50.811Z" }, + { url = "https://files.pythonhosted.org/packages/50/6d/39c0fbb8fc5cd4d2090811e553c2108cf5112e882f82505ee7495349a6bf/coverage-7.13.4-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c35eb28c1d085eb7d8c9b3296567a1bebe03ce72962e932431b9a61f28facf26", size = 261057, upload-time = "2026-02-09T12:57:52.447Z" }, + { url = "https://files.pythonhosted.org/packages/a4/a2/60010c669df5fa603bb5a97fb75407e191a846510da70ac657eb696b7fce/coverage-7.13.4-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:eb88b316ec33760714a4720feb2816a3a59180fd58c1985012054fa7aebee4c2", size = 263875, upload-time = "2026-02-09T12:57:53.938Z" }, + { url = "https://files.pythonhosted.org/packages/3e/d9/63b22a6bdbd17f1f96e9ed58604c2a6b0e72a9133e37d663bef185877cf6/coverage-7.13.4-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:7d41eead3cc673cbd38a4417deb7fd0b4ca26954ff7dc6078e33f6ff97bed940", size = 261500, upload-time = "2026-02-09T12:57:56.012Z" }, + { url = "https://files.pythonhosted.org/packages/70/bf/69f86ba1ad85bc3ad240e4c0e57a2e620fbc0e1645a47b5c62f0e941ad7f/coverage-7.13.4-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:fb26a934946a6afe0e326aebe0730cdff393a8bc0bbb65a2f41e30feddca399c", size = 265212, upload-time = "2026-02-09T12:57:57.5Z" }, + { url = "https://files.pythonhosted.org/packages/ae/f2/5f65a278a8c2148731831574c73e42f57204243d33bedaaf18fa79c5958f/coverage-7.13.4-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:dae88bc0fc77edaa65c14be099bd57ee140cf507e6bfdeea7938457ab387efb0", size = 260398, upload-time = "2026-02-09T12:57:59.027Z" }, + { url = "https://files.pythonhosted.org/packages/ef/80/6e8280a350ee9fea92f14b8357448a242dcaa243cb2c72ab0ca591f66c8c/coverage-7.13.4-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:845f352911777a8e722bfce168958214951e07e47e5d5d9744109fa5fe77f79b", size = 262584, upload-time = "2026-02-09T12:58:01.129Z" }, + { url = "https://files.pythonhosted.org/packages/92/11/a9cf762bb83386467737d32187756a42094927150c3e107df4cb078e8590/coverage-7.13.4-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:300deaee342f90696ed186e3a00c71b5b3d27bffe9e827677954f4ee56969601", size = 219522, upload-time = "2026-02-09T12:58:08.623Z" }, + { url = "https://files.pythonhosted.org/packages/d3/28/56e6d892b7b052236d67c95f1936b6a7cf7c3e2634bf27610b8cbd7f9c60/coverage-7.13.4-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:29e3220258d682b6226a9b0925bc563ed9a1ebcff3cad30f043eceea7eaf2689", size = 219855, upload-time = "2026-02-09T12:58:10.176Z" }, + { url = "https://files.pythonhosted.org/packages/e5/69/233459ee9eb0c0d10fcc2fe425a029b3fa5ce0f040c966ebce851d030c70/coverage-7.13.4-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:391ee8f19bef69210978363ca930f7328081c6a0152f1166c91f0b5fdd2a773c", size = 250887, upload-time = "2026-02-09T12:58:12.503Z" }, + { url = "https://files.pythonhosted.org/packages/06/90/2cdab0974b9b5bbc1623f7876b73603aecac11b8d95b85b5b86b32de5eab/coverage-7.13.4-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:0dd7ab8278f0d58a0128ba2fca25824321f05d059c1441800e934ff2efa52129", size = 253396, upload-time = "2026-02-09T12:58:14.615Z" }, + { url = "https://files.pythonhosted.org/packages/ac/15/ea4da0f85bf7d7b27635039e649e99deb8173fe551096ea15017f7053537/coverage-7.13.4-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:78cdf0d578b15148b009ccf18c686aa4f719d887e76e6b40c38ffb61d264a552", size = 254745, upload-time = "2026-02-09T12:58:16.162Z" }, + { url = "https://files.pythonhosted.org/packages/99/11/bb356e86920c655ca4d61daee4e2bbc7258f0a37de0be32d233b561134ff/coverage-7.13.4-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:48685fee12c2eb3b27c62f2658e7ea21e9c3239cba5a8a242801a0a3f6a8c62a", size = 257055, upload-time = "2026-02-09T12:58:17.892Z" }, + { url = "https://files.pythonhosted.org/packages/c9/0f/9ae1f8cb17029e09da06ca4e28c9e1d5c1c0a511c7074592e37e0836c915/coverage-7.13.4-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:4e83efc079eb39480e6346a15a1bcb3e9b04759c5202d157e1dd4303cd619356", size = 250911, upload-time = "2026-02-09T12:58:19.495Z" }, + { url = "https://files.pythonhosted.org/packages/89/3a/adfb68558fa815cbc29747b553bc833d2150228f251b127f1ce97e48547c/coverage-7.13.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ecae9737b72408d6a950f7e525f30aca12d4bd8dd95e37342e5beb3a2a8c4f71", size = 252754, upload-time = "2026-02-09T12:58:21.064Z" }, + { url = "https://files.pythonhosted.org/packages/32/b1/540d0c27c4e748bd3cd0bd001076ee416eda993c2bae47a73b7cc9357931/coverage-7.13.4-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:ae4578f8528569d3cf303fef2ea569c7f4c4059a38c8667ccef15c6e1f118aa5", size = 250720, upload-time = "2026-02-09T12:58:22.622Z" }, + { url = "https://files.pythonhosted.org/packages/c7/95/383609462b3ffb1fe133014a7c84fc0dd01ed55ac6140fa1093b5af7ebb1/coverage-7.13.4-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:6fdef321fdfbb30a197efa02d48fcd9981f0d8ad2ae8903ac318adc653f5df98", size = 254994, upload-time = "2026-02-09T12:58:24.548Z" }, + { url = "https://files.pythonhosted.org/packages/f7/ba/1761138e86c81680bfc3c49579d66312865457f9fe405b033184e5793cb3/coverage-7.13.4-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:2b0f6ccf3dbe577170bebfce1318707d0e8c3650003cb4b3a9dd744575daa8b5", size = 250531, upload-time = "2026-02-09T12:58:26.271Z" }, + { url = "https://files.pythonhosted.org/packages/f8/8e/05900df797a9c11837ab59c4d6fe94094e029582aab75c3309a93e6fb4e3/coverage-7.13.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:75fcd519f2a5765db3f0e391eb3b7d150cce1a771bf4c9f861aeab86c767a3c0", size = 252189, upload-time = "2026-02-09T12:58:27.807Z" }, + { url = "https://files.pythonhosted.org/packages/a7/e4/c884a405d6ead1370433dad1e3720216b4f9fd8ef5b64bfd984a2a60a11a/coverage-7.13.4-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:85480adfb35ffc32d40918aad81b89c69c9cc5661a9b8a81476d3e645321a056", size = 220246, upload-time = "2026-02-09T12:58:34.181Z" }, + { url = "https://files.pythonhosted.org/packages/81/5c/4d7ed8b23b233b0fffbc9dfec53c232be2e695468523242ea9fd30f97ad2/coverage-7.13.4-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:79be69cf7f3bf9b0deeeb062eab7ac7f36cd4cc4c4dd694bd28921ba4d8596cc", size = 220514, upload-time = "2026-02-09T12:58:35.704Z" }, + { url = "https://files.pythonhosted.org/packages/2f/6f/3284d4203fd2f28edd73034968398cd2d4cb04ab192abc8cff007ea35679/coverage-7.13.4-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:caa421e2684e382c5d8973ac55e4f36bed6821a9bad5c953494de960c74595c9", size = 261877, upload-time = "2026-02-09T12:58:37.864Z" }, + { url = "https://files.pythonhosted.org/packages/09/aa/b672a647bbe1556a85337dc95bfd40d146e9965ead9cc2fe81bde1e5cbce/coverage-7.13.4-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:14375934243ee05f56c45393fe2ce81fe5cc503c07cee2bdf1725fb8bef3ffaf", size = 264004, upload-time = "2026-02-09T12:58:39.492Z" }, + { url = "https://files.pythonhosted.org/packages/79/a1/aa384dbe9181f98bba87dd23dda436f0c6cf2e148aecbb4e50fc51c1a656/coverage-7.13.4-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:25a41c3104d08edb094d9db0d905ca54d0cd41c928bb6be3c4c799a54753af55", size = 266408, upload-time = "2026-02-09T12:58:41.852Z" }, + { url = "https://files.pythonhosted.org/packages/53/5e/5150bf17b4019bc600799f376bb9606941e55bd5a775dc1e096b6ffea952/coverage-7.13.4-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:6f01afcff62bf9a08fb32b2c1d6e924236c0383c02c790732b6537269e466a72", size = 267544, upload-time = "2026-02-09T12:58:44.093Z" }, + { url = "https://files.pythonhosted.org/packages/e0/ed/f1de5c675987a4a7a672250d2c5c9d73d289dbf13410f00ed7181d8017dd/coverage-7.13.4-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:eb9078108fbf0bcdde37c3f4779303673c2fa1fe8f7956e68d447d0dd426d38a", size = 260980, upload-time = "2026-02-09T12:58:45.721Z" }, + { url = "https://files.pythonhosted.org/packages/b3/e3/fe758d01850aa172419a6743fe76ba8b92c29d181d4f676ffe2dae2ba631/coverage-7.13.4-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:0e086334e8537ddd17e5f16a344777c1ab8194986ec533711cbe6c41cde841b6", size = 263871, upload-time = "2026-02-09T12:58:47.334Z" }, + { url = "https://files.pythonhosted.org/packages/b6/76/b829869d464115e22499541def9796b25312b8cf235d3bb00b39f1675395/coverage-7.13.4-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:725d985c5ab621268b2edb8e50dfe57633dc69bda071abc470fed55a14935fd3", size = 261472, upload-time = "2026-02-09T12:58:48.995Z" }, + { url = "https://files.pythonhosted.org/packages/14/9e/caedb1679e73e2f6ad240173f55218488bfe043e38da577c4ec977489915/coverage-7.13.4-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:3c06f0f1337c667b971ca2f975523347e63ec5e500b9aa5882d91931cd3ef750", size = 265210, upload-time = "2026-02-09T12:58:51.178Z" }, + { url = "https://files.pythonhosted.org/packages/3a/10/0dd02cb009b16ede425b49ec344aba13a6ae1dc39600840ea6abcb085ac4/coverage-7.13.4-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:590c0ed4bf8e85f745e6b805b2e1c457b2e33d5255dd9729743165253bc9ad39", size = 260319, upload-time = "2026-02-09T12:58:53.081Z" }, + { url = "https://files.pythonhosted.org/packages/92/8e/234d2c927af27c6d7a5ffad5bd2cf31634c46a477b4c7adfbfa66baf7ebb/coverage-7.13.4-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:eb30bf180de3f632cd043322dad5751390e5385108b2807368997d1a92a509d0", size = 262638, upload-time = "2026-02-09T12:58:55.258Z" }, + { url = "https://files.pythonhosted.org/packages/0d/4a/331fe2caf6799d591109bb9c08083080f6de90a823695d412a935622abb2/coverage-7.13.4-py3-none-any.whl", hash = "sha256:1af1641e57cf7ba1bd67d677c9abdbcd6cc2ab7da3bca7fa1e2b7e50e65f2ad0", size = 211242, upload-time = "2026-02-09T12:59:02.032Z" }, ] [[package]] @@ -247,11 +257,11 @@ wheels = [ [[package]] name = "filelock" -version = "3.20.3" +version = "3.24.3" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/1d/65/ce7f1b70157833bf3cb851b556a37d4547ceafc158aa9b34b36782f23696/filelock-3.20.3.tar.gz", hash = "sha256:18c57ee915c7ec61cff0ecf7f0f869936c7c30191bb0cf406f1341778d0834e1", size = 19485, upload-time = "2026-01-09T17:55:05.421Z" } +sdist = { url = "https://files.pythonhosted.org/packages/73/92/a8e2479937ff39185d20dd6a851c1a63e55849e447a55e798cc2e1f49c65/filelock-3.24.3.tar.gz", hash = "sha256:011a5644dc937c22699943ebbfc46e969cdde3e171470a6e40b9533e5a72affa", size = 37935, upload-time = "2026-02-19T00:48:20.543Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b5/36/7fb70f04bf00bc646cd5bb45aa9eddb15e19437a28b8fb2b4a5249fac770/filelock-3.20.3-py3-none-any.whl", hash = "sha256:4b0dda527ee31078689fc205ec4f1c1bf7d56cf88b6dc9426c4f230e46c2dce1", size = 16701, upload-time = "2026-01-09T17:55:04.334Z" }, + { url = "https://files.pythonhosted.org/packages/9c/0f/5d0c71a1aefeb08efff26272149e07ab922b64f46c63363756224bd6872e/filelock-3.24.3-py3-none-any.whl", hash = "sha256:426e9a4660391f7f8a810d71b0555bce9008b0a1cc342ab1f6947d37639e002d", size = 24331, upload-time = "2026-02-19T00:48:18.465Z" }, ] [[package]] @@ -283,11 +293,11 @@ wheels = [ [[package]] name = "isort" -version = "7.0.0" +version = "8.0.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/63/53/4f3c058e3bace40282876f9b553343376ee687f3c35a525dc79dbd450f88/isort-7.0.0.tar.gz", hash = "sha256:5513527951aadb3ac4292a41a16cbc50dd1642432f5e8c20057d414bdafb4187", size = 805049, upload-time = "2025-10-11T13:30:59.107Z" } +sdist = { url = "https://files.pythonhosted.org/packages/ef/7c/ec4ab396d31b3b395e2e999c8f46dec78c5e29209fac49d1f4dace04041d/isort-8.0.1.tar.gz", hash = "sha256:171ac4ff559cdc060bcfff550bc8404a486fee0caab245679c2abe7cb253c78d", size = 769592, upload-time = "2026-02-28T10:08:20.685Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/7f/ed/e3705d6d02b4f7aea715a353c8ce193efd0b5db13e204df895d38734c244/isort-7.0.0-py3-none-any.whl", hash = "sha256:1bcabac8bc3c36c7fb7b98a76c8abb18e0f841a3ba81decac7691008592499c1", size = 94672, upload-time = "2025-10-11T13:30:57.665Z" }, + { url = "https://files.pythonhosted.org/packages/3e/95/c7c34aa53c16353c56d0b802fba48d5f5caa2cdee7958acbcb795c830416/isort-8.0.1-py3-none-any.whl", hash = "sha256:28b89bc70f751b559aeca209e6120393d43fbe2490de0559662be7a9787e3d75", size = 89733, upload-time = "2026-02-28T10:08:19.466Z" }, ] [[package]] @@ -424,20 +434,20 @@ wheels = [ [[package]] name = "pip" -version = "25.3" +version = "26.0.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/fe/6e/74a3f0179a4a73a53d66ce57fdb4de0080a8baa1de0063de206d6167acc2/pip-25.3.tar.gz", hash = "sha256:8d0538dbbd7babbd207f261ed969c65de439f6bc9e5dbd3b3b9a77f25d95f343", size = 1803014, upload-time = "2025-10-25T00:55:41.394Z" } +sdist = { url = "https://files.pythonhosted.org/packages/48/83/0d7d4e9efe3344b8e2fe25d93be44f64b65364d3c8d7bc6dc90198d5422e/pip-26.0.1.tar.gz", hash = "sha256:c4037d8a277c89b320abe636d59f91e6d0922d08a05b60e85e53b296613346d8", size = 1812747, upload-time = "2026-02-05T02:20:18.702Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/44/3c/d717024885424591d5376220b5e836c2d5293ce2011523c9de23ff7bf068/pip-25.3-py3-none-any.whl", hash = "sha256:9655943313a94722b7774661c21049070f6bbb0a1516bf02f7c8d5d9201514cd", size = 1778622, upload-time = "2025-10-25T00:55:39.247Z" }, + { url = "https://files.pythonhosted.org/packages/de/f0/c81e05b613866b76d2d1066490adf1a3dbc4ee9d9c839961c3fc8a6997af/pip-26.0.1-py3-none-any.whl", hash = "sha256:bdb1b08f4274833d62c1aa29e20907365a2ceb950410df15fc9521bad440122b", size = 1787723, upload-time = "2026-02-05T02:20:16.416Z" }, ] [[package]] name = "platformdirs" -version = "4.5.1" +version = "4.9.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/cf/86/0248f086a84f01b37aaec0fa567b397df1a119f73c16f6c7a9aac73ea309/platformdirs-4.5.1.tar.gz", hash = "sha256:61d5cdcc6065745cdd94f0f878977f8de9437be93de97c1c12f853c9c0cdcbda", size = 21715, upload-time = "2025-12-05T13:52:58.638Z" } +sdist = { url = "https://files.pythonhosted.org/packages/1b/04/fea538adf7dbbd6d186f551d595961e564a3b6715bdf276b477460858672/platformdirs-4.9.2.tar.gz", hash = "sha256:9a33809944b9db043ad67ca0db94b14bf452cc6aeaac46a88ea55b26e2e9d291", size = 28394, upload-time = "2026-02-16T03:56:10.574Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/cb/28/3bfe2fa5a7b9c46fe7e13c97bda14c895fb10fa2ebf1d0abb90e0cea7ee1/platformdirs-4.5.1-py3-none-any.whl", hash = "sha256:d03afa3963c806a9bed9d5125c8f4cb2fdaf74a55ab60e5d59b3fde758104d31", size = 18731, upload-time = "2025-12-05T13:52:56.823Z" }, + { url = "https://files.pythonhosted.org/packages/48/31/05e764397056194206169869b50cf2fee4dbbbc71b344705b9c0d878d4d8/platformdirs-4.9.2-py3-none-any.whl", hash = "sha256:9170634f126f8efdae22fb58ae8a0eaa86f38365bc57897a6c4f781d1f5875bd", size = 21168, upload-time = "2026-02-16T03:56:08.891Z" }, ] [[package]] @@ -556,16 +566,16 @@ wheels = [ [[package]] name = "pyjwt" -version = "2.10.1" +version = "2.11.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e7/46/bd74733ff231675599650d3e47f361794b22ef3e3770998dda30d3b63726/pyjwt-2.10.1.tar.gz", hash = "sha256:3cc5772eb20009233caf06e9d8a0577824723b44e6648ee0a2aedb6cf9381953", size = 87785, upload-time = "2024-11-28T03:43:29.933Z" } +sdist = { url = "https://files.pythonhosted.org/packages/5c/5a/b46fa56bf322901eee5b0454a34343cdbdae202cd421775a8ee4e42fd519/pyjwt-2.11.0.tar.gz", hash = "sha256:35f95c1f0fbe5d5ba6e43f00271c275f7a1a4db1dab27bf708073b75318ea623", size = 98019, upload-time = "2026-01-30T19:59:55.694Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/61/ad/689f02752eeec26aed679477e80e632ef1b682313be70793d798c1d5fc8f/PyJWT-2.10.1-py3-none-any.whl", hash = "sha256:dcdd193e30abefd5debf142f9adfcdd2b58004e644f25406ffaebd50bd98dacb", size = 22997, upload-time = "2024-11-28T03:43:27.893Z" }, + { url = "https://files.pythonhosted.org/packages/6f/01/c26ce75ba460d5cd503da9e13b21a33804d38c2165dec7b716d06b13010c/pyjwt-2.11.0-py3-none-any.whl", hash = "sha256:94a6bde30eb5c8e04fee991062b534071fd1439ef58d2adc9ccb823e7bcd0469", size = 28224, upload-time = "2026-01-30T19:59:54.539Z" }, ] [[package]] name = "pylint" -version = "4.0.4" +version = "4.0.5" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "astroid", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, @@ -575,9 +585,9 @@ dependencies = [ { name = "platformdirs", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, { name = "tomlkit", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/5a/d2/b081da1a8930d00e3fc06352a1d449aaf815d4982319fab5d8cdb2e9ab35/pylint-4.0.4.tar.gz", hash = "sha256:d9b71674e19b1c36d79265b5887bf8e55278cbe236c9e95d22dc82cf044fdbd2", size = 1571735, upload-time = "2025-11-30T13:29:04.315Z" } +sdist = { url = "https://files.pythonhosted.org/packages/e4/b6/74d9a8a68b8067efce8d07707fe6a236324ee1e7808d2eb3646ec8517c7d/pylint-4.0.5.tar.gz", hash = "sha256:8cd6a618df75deb013bd7eb98327a95f02a6fb839205a6bbf5456ef96afb317c", size = 1572474, upload-time = "2026-02-20T09:07:33.621Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/a6/92/d40f5d937517cc489ad848fc4414ecccc7592e4686b9071e09e64f5e378e/pylint-4.0.4-py3-none-any.whl", hash = "sha256:63e06a37d5922555ee2c20963eb42559918c20bd2b21244e4ef426e7c43b92e0", size = 536425, upload-time = "2025-11-30T13:29:02.53Z" }, + { url = "https://files.pythonhosted.org/packages/d5/6f/9ac2548e290764781f9e7e2aaf0685b086379dabfb29ca38536985471eaf/pylint-4.0.5-py3-none-any.whl", hash = "sha256:00f51c9b14a3b3ae08cff6b2cdd43f28165c78b165b628692e428fb1f8dc2cf2", size = 536694, upload-time = "2026-02-20T09:07:31.028Z" }, ] [[package]] @@ -634,6 +644,19 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892, upload-time = "2024-03-01T18:36:18.57Z" }, ] +[[package]] +name = "python-discovery" +version = "1.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "filelock", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "platformdirs", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/82/bb/93a3e83bdf9322c7e21cafd092e56a4a17c4d8ef4277b6eb01af1a540a6f/python_discovery-1.1.0.tar.gz", hash = "sha256:447941ba1aed8cc2ab7ee3cb91be5fc137c5bdbb05b7e6ea62fbdcb66e50b268", size = 55674, upload-time = "2026-02-26T09:42:49.668Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/06/54/82a6e2ef37f0f23dccac604b9585bdcbd0698604feb64807dcb72853693e/python_discovery-1.1.0-py3-none-any.whl", hash = "sha256:a162893b8809727f54594a99ad2179d2ede4bf953e12d4c7abc3cc9cdbd1437b", size = 30687, upload-time = "2026-02-26T09:42:48.548Z" }, +] + [[package]] name = "pyyaml" version = "6.0.3" @@ -687,38 +710,37 @@ wheels = [ [[package]] name = "rich" -version = "14.2.0" +version = "14.3.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "markdown-it-py", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, { name = "pygments", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/fb/d2/8920e102050a0de7bfabeb4c4614a49248cf8d5d7a8d01885fbb24dc767a/rich-14.2.0.tar.gz", hash = "sha256:73ff50c7c0c1c77c8243079283f4edb376f0f6442433aecb8ce7e6d0b92d1fe4", size = 219990, upload-time = "2025-10-09T14:16:53.064Z" } +sdist = { url = "https://files.pythonhosted.org/packages/b3/c6/f3b320c27991c46f43ee9d856302c70dc2d0fb2dba4842ff739d5f46b393/rich-14.3.3.tar.gz", hash = "sha256:b8daa0b9e4eef54dd8cf7c86c03713f53241884e814f4e2f5fb342fe520f639b", size = 230582, upload-time = "2026-02-19T17:23:12.474Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/25/7a/b0178788f8dc6cafce37a212c99565fa1fe7872c70c6c9c1e1a372d9d88f/rich-14.2.0-py3-none-any.whl", hash = "sha256:76bc51fe2e57d2b1be1f96c524b890b816e334ab4c1e45888799bfaab0021edd", size = 243393, upload-time = "2025-10-09T14:16:51.245Z" }, + { url = "https://files.pythonhosted.org/packages/14/25/b208c5683343959b670dc001595f2f3737e051da617f66c31f7c4fa93abc/rich-14.3.3-py3-none-any.whl", hash = "sha256:793431c1f8619afa7d3b52b2cdec859562b950ea0d4b6b505397612db8d5362d", size = 310458, upload-time = "2026-02-19T17:23:13.732Z" }, ] [[package]] name = "ruff" -version = "0.14.14" +version = "0.15.4" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/2e/06/f71e3a86b2df0dfa2d2f72195941cd09b44f87711cb7fa5193732cb9a5fc/ruff-0.14.14.tar.gz", hash = "sha256:2d0f819c9a90205f3a867dbbd0be083bee9912e170fd7d9704cc8ae45824896b", size = 4515732, upload-time = "2026-01-22T22:30:17.527Z" } +sdist = { url = "https://files.pythonhosted.org/packages/da/31/d6e536cdebb6568ae75a7f00e4b4819ae0ad2640c3604c305a0428680b0c/ruff-0.15.4.tar.gz", hash = "sha256:3412195319e42d634470cc97aa9803d07e9d5c9223b99bcb1518f0c725f26ae1", size = 4569550, upload-time = "2026-02-26T20:04:14.959Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d2/89/20a12e97bc6b9f9f68343952da08a8099c57237aef953a56b82711d55edd/ruff-0.14.14-py3-none-linux_armv6l.whl", hash = "sha256:7cfe36b56e8489dee8fbc777c61959f60ec0f1f11817e8f2415f429552846aed", size = 10467650, upload-time = "2026-01-22T22:30:08.578Z" }, - { url = "https://files.pythonhosted.org/packages/a3/b1/c5de3fd2d5a831fcae21beda5e3589c0ba67eec8202e992388e4b17a6040/ruff-0.14.14-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:6006a0082336e7920b9573ef8a7f52eec837add1265cc74e04ea8a4368cd704c", size = 10883245, upload-time = "2026-01-22T22:30:04.155Z" }, - { url = "https://files.pythonhosted.org/packages/b8/7c/3c1db59a10e7490f8f6f8559d1db8636cbb13dccebf18686f4e3c9d7c772/ruff-0.14.14-py3-none-macosx_11_0_arm64.whl", hash = "sha256:026c1d25996818f0bf498636686199d9bd0d9d6341c9c2c3b62e2a0198b758de", size = 10231273, upload-time = "2026-01-22T22:30:34.642Z" }, - { url = "https://files.pythonhosted.org/packages/a1/6e/5e0e0d9674be0f8581d1f5e0f0a04761203affce3232c1a1189d0e3b4dad/ruff-0.14.14-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f666445819d31210b71e0a6d1c01e24447a20b85458eea25a25fe8142210ae0e", size = 10585753, upload-time = "2026-01-22T22:30:31.781Z" }, - { url = "https://files.pythonhosted.org/packages/23/09/754ab09f46ff1884d422dc26d59ba18b4e5d355be147721bb2518aa2a014/ruff-0.14.14-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3c0f18b922c6d2ff9a5e6c3ee16259adc513ca775bcf82c67ebab7cbd9da5bc8", size = 10286052, upload-time = "2026-01-22T22:30:24.827Z" }, - { url = "https://files.pythonhosted.org/packages/c8/cc/e71f88dd2a12afb5f50733851729d6b571a7c3a35bfdb16c3035132675a0/ruff-0.14.14-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1629e67489c2dea43e8658c3dba659edbfd87361624b4040d1df04c9740ae906", size = 11043637, upload-time = "2026-01-22T22:30:13.239Z" }, - { url = "https://files.pythonhosted.org/packages/67/b2/397245026352494497dac935d7f00f1468c03a23a0c5db6ad8fc49ca3fb2/ruff-0.14.14-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:27493a2131ea0f899057d49d303e4292b2cae2bb57253c1ed1f256fbcd1da480", size = 12194761, upload-time = "2026-01-22T22:30:22.542Z" }, - { url = "https://files.pythonhosted.org/packages/5b/06/06ef271459f778323112c51b7587ce85230785cd64e91772034ddb88f200/ruff-0.14.14-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:01ff589aab3f5b539e35db38425da31a57521efd1e4ad1ae08fc34dbe30bd7df", size = 12005701, upload-time = "2026-01-22T22:30:20.499Z" }, - { url = "https://files.pythonhosted.org/packages/41/d6/99364514541cf811ccc5ac44362f88df66373e9fec1b9d1c4cc830593fe7/ruff-0.14.14-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1cc12d74eef0f29f51775f5b755913eb523546b88e2d733e1d701fe65144e89b", size = 11282455, upload-time = "2026-01-22T22:29:59.679Z" }, - { url = "https://files.pythonhosted.org/packages/ca/71/37daa46f89475f8582b7762ecd2722492df26421714a33e72ccc9a84d7a5/ruff-0.14.14-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bb8481604b7a9e75eff53772496201690ce2687067e038b3cc31aaf16aa0b974", size = 11215882, upload-time = "2026-01-22T22:29:57.032Z" }, - { url = "https://files.pythonhosted.org/packages/2c/10/a31f86169ec91c0705e618443ee74ede0bdd94da0a57b28e72db68b2dbac/ruff-0.14.14-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:14649acb1cf7b5d2d283ebd2f58d56b75836ed8c6f329664fa91cdea19e76e66", size = 11180549, upload-time = "2026-01-22T22:30:27.175Z" }, - { url = "https://files.pythonhosted.org/packages/fd/1e/c723f20536b5163adf79bdd10c5f093414293cdf567eed9bdb7b83940f3f/ruff-0.14.14-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:e8058d2145566510790eab4e2fad186002e288dec5e0d343a92fe7b0bc1b3e13", size = 10543416, upload-time = "2026-01-22T22:30:01.964Z" }, - { url = "https://files.pythonhosted.org/packages/3e/34/8a84cea7e42c2d94ba5bde1d7a4fae164d6318f13f933d92da6d7c2041ff/ruff-0.14.14-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:e651e977a79e4c758eb807f0481d673a67ffe53cfa92209781dfa3a996cf8412", size = 10285491, upload-time = "2026-01-22T22:30:29.51Z" }, - { url = "https://files.pythonhosted.org/packages/55/ef/b7c5ea0be82518906c978e365e56a77f8de7678c8bb6651ccfbdc178c29f/ruff-0.14.14-py3-none-musllinux_1_2_i686.whl", hash = "sha256:cc8b22da8d9d6fdd844a68ae937e2a0adf9b16514e9a97cc60355e2d4b219fc3", size = 10733525, upload-time = "2026-01-22T22:30:06.499Z" }, - { url = "https://files.pythonhosted.org/packages/6a/5b/aaf1dfbcc53a2811f6cc0a1759de24e4b03e02ba8762daabd9b6bd8c59e3/ruff-0.14.14-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:16bc890fb4cc9781bb05beb5ab4cd51be9e7cb376bf1dd3580512b24eb3fda2b", size = 11315626, upload-time = "2026-01-22T22:30:36.848Z" }, + { url = "https://files.pythonhosted.org/packages/f2/82/c11a03cfec3a4d26a0ea1e571f0f44be5993b923f905eeddfc397c13d360/ruff-0.15.4-py3-none-linux_armv6l.whl", hash = "sha256:a1810931c41606c686bae8b5b9a8072adac2f611bb433c0ba476acba17a332e0", size = 10453333, upload-time = "2026-02-26T20:04:20.093Z" }, + { url = "https://files.pythonhosted.org/packages/ce/5d/6a1f271f6e31dffb31855996493641edc3eef8077b883eaf007a2f1c2976/ruff-0.15.4-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:5a1632c66672b8b4d3e1d1782859e98d6e0b4e70829530666644286600a33992", size = 10853356, upload-time = "2026-02-26T20:04:05.808Z" }, + { url = "https://files.pythonhosted.org/packages/b1/d8/0fab9f8842b83b1a9c2bf81b85063f65e93fb512e60effa95b0be49bfc54/ruff-0.15.4-py3-none-macosx_11_0_arm64.whl", hash = "sha256:a4386ba2cd6c0f4ff75252845906acc7c7c8e1ac567b7bc3d373686ac8c222ba", size = 10187434, upload-time = "2026-02-26T20:03:54.656Z" }, + { url = "https://files.pythonhosted.org/packages/85/cc/cc220fd9394eff5db8d94dec199eec56dd6c9f3651d8869d024867a91030/ruff-0.15.4-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b2496488bdfd3732747558b6f95ae427ff066d1fcd054daf75f5a50674411e75", size = 10535456, upload-time = "2026-02-26T20:03:52.738Z" }, + { url = "https://files.pythonhosted.org/packages/fa/0f/bced38fa5cf24373ec767713c8e4cadc90247f3863605fb030e597878661/ruff-0.15.4-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3f1c4893841ff2d54cbda1b2860fa3260173df5ddd7b95d370186f8a5e66a4ac", size = 10287772, upload-time = "2026-02-26T20:04:08.138Z" }, + { url = "https://files.pythonhosted.org/packages/2b/90/58a1802d84fed15f8f281925b21ab3cecd813bde52a8ca033a4de8ab0e7a/ruff-0.15.4-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:820b8766bd65503b6c30aaa6331e8ef3a6e564f7999c844e9a547c40179e440a", size = 11049051, upload-time = "2026-02-26T20:04:03.53Z" }, + { url = "https://files.pythonhosted.org/packages/d2/ac/b7ad36703c35f3866584564dc15f12f91cb1a26a897dc2fd13d7cb3ae1af/ruff-0.15.4-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c9fb74bab47139c1751f900f857fa503987253c3ef89129b24ed375e72873e85", size = 11890494, upload-time = "2026-02-26T20:04:10.497Z" }, + { url = "https://files.pythonhosted.org/packages/93/3d/3eb2f47a39a8b0da99faf9c54d3eb24720add1e886a5309d4d1be73a6380/ruff-0.15.4-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f80c98765949c518142b3a50a5db89343aa90f2c2bf7799de9986498ae6176db", size = 11326221, upload-time = "2026-02-26T20:04:12.84Z" }, + { url = "https://files.pythonhosted.org/packages/ff/90/bf134f4c1e5243e62690e09d63c55df948a74084c8ac3e48a88468314da6/ruff-0.15.4-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:451a2e224151729b3b6c9ffb36aed9091b2996fe4bdbd11f47e27d8f2e8888ec", size = 11168459, upload-time = "2026-02-26T20:04:00.969Z" }, + { url = "https://files.pythonhosted.org/packages/b5/e5/a64d27688789b06b5d55162aafc32059bb8c989c61a5139a36e1368285eb/ruff-0.15.4-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:a8f157f2e583c513c4f5f896163a93198297371f34c04220daf40d133fdd4f7f", size = 11104366, upload-time = "2026-02-26T20:03:48.099Z" }, + { url = "https://files.pythonhosted.org/packages/f1/f6/32d1dcb66a2559763fc3027bdd65836cad9eb09d90f2ed6a63d8e9252b02/ruff-0.15.4-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:917cc68503357021f541e69b35361c99387cdbbf99bd0ea4aa6f28ca99ff5338", size = 10510887, upload-time = "2026-02-26T20:03:45.771Z" }, + { url = "https://files.pythonhosted.org/packages/ff/92/22d1ced50971c5b6433aed166fcef8c9343f567a94cf2b9d9089f6aa80fe/ruff-0.15.4-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:e9737c8161da79fd7cfec19f1e35620375bd8b2a50c3e77fa3d2c16f574105cc", size = 10285939, upload-time = "2026-02-26T20:04:22.42Z" }, + { url = "https://files.pythonhosted.org/packages/e6/f4/7c20aec3143837641a02509a4668fb146a642fd1211846634edc17eb5563/ruff-0.15.4-py3-none-musllinux_1_2_i686.whl", hash = "sha256:291258c917539e18f6ba40482fe31d6f5ac023994ee11d7bdafd716f2aab8a68", size = 10765471, upload-time = "2026-02-26T20:03:58.924Z" }, + { url = "https://files.pythonhosted.org/packages/d0/09/6d2f7586f09a16120aebdff8f64d962d7c4348313c77ebb29c566cefc357/ruff-0.15.4-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:3f83c45911da6f2cd5936c436cf86b9f09f09165f033a99dcf7477e34041cbc3", size = 11263382, upload-time = "2026-02-26T20:04:24.424Z" }, ] [[package]] @@ -732,11 +754,11 @@ wheels = [ [[package]] name = "stevedore" -version = "5.6.0" +version = "5.7.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/96/5b/496f8abebd10c3301129abba7ddafd46c71d799a70c44ab080323987c4c9/stevedore-5.6.0.tar.gz", hash = "sha256:f22d15c6ead40c5bbfa9ca54aa7e7b4a07d59b36ae03ed12ced1a54cf0b51945", size = 516074, upload-time = "2025-11-20T10:06:07.264Z" } +sdist = { url = "https://files.pythonhosted.org/packages/a2/6d/90764092216fa560f6587f83bb70113a8ba510ba436c6476a2b47359057c/stevedore-5.7.0.tar.gz", hash = "sha256:31dd6fe6b3cbe921e21dcefabc9a5f1cf848cf538a1f27543721b8ca09948aa3", size = 516200, upload-time = "2026-02-20T13:27:06.765Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f4/40/8561ce06dc46fd17242c7724ab25b257a2ac1b35f4ebf551b40ce6105cfa/stevedore-5.6.0-py3-none-any.whl", hash = "sha256:4a36dccefd7aeea0c70135526cecb7766c4c84c473b1af68db23d541b6dc1820", size = 54428, upload-time = "2025-11-20T10:06:05.946Z" }, + { url = "https://files.pythonhosted.org/packages/69/06/36d260a695f383345ab5bbc3fd447249594ae2fa8dfd19c533d5ae23f46b/stevedore-5.7.0-py3-none-any.whl", hash = "sha256:fd25efbb32f1abb4c9e502f385f0018632baac11f9ee5d1b70f88cc5e22ad4ed", size = 54483, upload-time = "2026-02-20T13:27:05.561Z" }, ] [[package]] @@ -750,11 +772,11 @@ wheels = [ [[package]] name = "tqdm" -version = "4.67.1" +version = "4.67.3" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a8/4b/29b4ef32e036bb34e4ab51796dd745cdba7ed47ad142a9f4a1eb8e0c744d/tqdm-4.67.1.tar.gz", hash = "sha256:f8aef9c52c08c13a65f30ea34f4e5aac3fd1a34959879d7e59e63027286627f2", size = 169737, upload-time = "2024-11-24T20:12:22.481Z" } +sdist = { url = "https://files.pythonhosted.org/packages/09/a9/6ba95a270c6f1fbcd8dac228323f2777d886cb206987444e4bce66338dd4/tqdm-4.67.3.tar.gz", hash = "sha256:7d825f03f89244ef73f1d4ce193cb1774a8179fd96f31d7e1dcde62092b960bb", size = 169598, upload-time = "2026-02-03T17:35:53.048Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d0/30/dc54f88dd4a2b5dc8a0279bdd7270e735851848b762aeb1c1184ed1f6b14/tqdm-4.67.1-py3-none-any.whl", hash = "sha256:26445eca388f82e72884e0d580d5464cd801a3ea01e63e5601bdff9ba6a48de2", size = 78540, upload-time = "2024-11-24T20:12:19.698Z" }, + { url = "https://files.pythonhosted.org/packages/16/e1/3079a9ff9b8e11b846c6ac5c8b5bfb7ff225eee721825310c91b3b50304f/tqdm-4.67.3-py3-none-any.whl", hash = "sha256:ee1e4c0e59148062281c49d80b25b67771a127c85fc9676d3be5f243206826bf", size = 78374, upload-time = "2026-02-03T17:35:50.982Z" }, ] [[package]] @@ -789,16 +811,17 @@ wheels = [ [[package]] name = "virtualenv" -version = "20.36.1" +version = "21.1.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "distlib", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, { name = "filelock", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, { name = "platformdirs", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, + { name = "python-discovery", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/aa/a3/4d310fa5f00863544e1d0f4de93bddec248499ccf97d4791bc3122c9d4f3/virtualenv-20.36.1.tar.gz", hash = "sha256:8befb5c81842c641f8ee658481e42641c68b5eab3521d8e092d18320902466ba", size = 6032239, upload-time = "2026-01-09T18:21:01.296Z" } +sdist = { url = "https://files.pythonhosted.org/packages/2f/c9/18d4b36606d6091844daa3bd93cf7dc78e6f5da21d9f21d06c221104b684/virtualenv-21.1.0.tar.gz", hash = "sha256:1990a0188c8f16b6b9cf65c9183049007375b26aad415514d377ccacf1e4fb44", size = 5840471, upload-time = "2026-02-27T08:49:29.702Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/6a/2a/dc2228b2888f51192c7dc766106cd475f1b768c10caaf9727659726f7391/virtualenv-20.36.1-py3-none-any.whl", hash = "sha256:575a8d6b124ef88f6f51d56d656132389f961062a9177016a50e4f507bbcc19f", size = 6008258, upload-time = "2026-01-09T18:20:59.425Z" }, + { url = "https://files.pythonhosted.org/packages/78/55/896b06bf93a49bec0f4ae2a6f1ed12bd05c8860744ac3a70eda041064e4d/virtualenv-21.1.0-py3-none-any.whl", hash = "sha256:164f5e14c5587d170cf98e60378eb91ea35bf037be313811905d3a24ea33cc07", size = 5825072, upload-time = "2026-02-27T08:49:27.516Z" }, ] [[package]] diff --git a/zkb/__main__.py b/zkb/__main__.py index f94411e..34a9969 100644 --- a/zkb/__main__.py +++ b/zkb/__main__.py @@ -1,8 +1,11 @@ +from enum import EnumType import os import io import sys import json +import logging import argparse +from typing import Any from pathlib import Path from importlib.metadata import version @@ -10,6 +13,7 @@ from zkb.core import KernelBuilder, AssetsCollector from zkb.tools import cleaning as cm, commands as ccmd, Logger as logger +from zkb.enums import EnumChroot, EnumCommand, EnumEnvironment, EnumContainerEnvironment, EnumKernelBase, EnumPackageType from zkb.configs import ArgumentConfig, DirectoryConfig as dcfg from zkb.engines import GenericContainerEngine from zkb.commands import KernelCommand, AssetsCommand, BundleCommand @@ -47,9 +51,9 @@ def parse_args() -> argparse.Namespace: # parser and subparsers parser_parent = argparse.ArgumentParser(description="Advanced Android kernel builder with Kali NetHunter support.") subparsers = parser_parent.add_subparsers(dest="command") - parser_kernel = subparsers.add_parser("kernel", help="build the kernel") - parser_assets = subparsers.add_parser("assets", help="collect assets") - parser_bundle = subparsers.add_parser("bundle", help="build the kernel + collect assets") + parser_kernel = subparsers.add_parser(EnumCommand.KERNEL.value, help="build the kernel") + parser_assets = subparsers.add_parser(EnumCommand.ASSETS.value, help="collect assets") + parser_bundle = subparsers.add_parser(EnumCommand.BUNDLE.value, help="build the kernel + collect assets") # main parser arguments parser_parent.add_argument( @@ -74,9 +78,9 @@ def parse_args() -> argparse.Namespace: "name_or_flags": ("--build-env",), "config": { "required": True, - "dest": "build_env", - "type": str, - "choices": {"local", "docker", "podman"}, + "dest": "benv", + "type": EnumEnvironment.from_string, + "choices": tuple(EnumEnvironment), "help": "build environment" } } @@ -85,8 +89,8 @@ def parse_args() -> argparse.Namespace: "config": { "required": True, "dest": "base", - "type": str, - "choices": {"los", "pa", "x", "aosp"}, + "type": EnumKernelBase.from_string, + "choices": tuple(EnumKernelBase), "help": "kernel source base" } } @@ -150,7 +154,7 @@ def parse_args() -> argparse.Namespace: "--chroot", type=str, required=True, - choices=("full", "minimal"), + choices=EnumChroot, help="select Kali chroot type" ) parser_assets.add_argument( @@ -179,7 +183,7 @@ def parse_args() -> argparse.Namespace: type=str, required=True, dest="package_type", - choices={"conan", "slim", "full"}, + choices=EnumPackageType, help="select package type of the bundle" ) parser_bundle.add_argument( @@ -194,6 +198,7 @@ def parse_args() -> argparse.Namespace: def main() -> None: args = parse_args() logger().get_logger() # type: ignore + log = logging.getLogger("ZeroKernelLogger") # start preparing the environment os.chdir(dcfg.root) @@ -209,16 +214,18 @@ def main() -> None: if args.command != "assets" and args.defconfig: args.defconfig = args.defconfig if args.defconfig.is_absolute() else Path.cwd() / args.defconfig arguments = vars(args) + log.debug(f"Arguments are: {arguments}") + acfg = ArgumentConfig(**arguments) acfg.check_settings() # determine the build variation match args.benv: - case "docker" | "podman": + case EnumContainerEnvironment.DOCKER | EnumContainerEnvironment.PODMAN: with GenericContainerEngine(**json.loads(acfg.model_dump_json())) as engined_cmd: ccmd.launch(engined_cmd) - case "local": + case EnumEnvironment.LOCAL: kernel_builder = KernelBuilder( codename = args.codename, base = args.base, @@ -242,15 +249,15 @@ def main() -> None: ) match args.command: - case "kernel": + case EnumCommand.KERNEL: kc = KernelCommand(kernel_builder=kernel_builder) kc.execute() - case "assets": + case EnumCommand.ASSETS: ac = AssetsCommand(assets_collector=assets_collector) ac.execute() - case "bundle": + case EnumCommand.BUNDLE: bc = BundleCommand( kernel_builder = kernel_builder, assets_collector = assets_collector, diff --git a/zkb/clients/github.py b/zkb/clients/github.py index e10623f..c78fd16 100644 --- a/zkb/clients/github.py +++ b/zkb/clients/github.py @@ -17,14 +17,14 @@ class GithubApiClient(ModelConfig): """Client for limited interaction with GitHub API. :param str project: GitHub project name (owner/repo). - :param Optional[str]=None file_filter: A filter to select specific files from project's artifacts. + :param typing.Optional[str]=None file_filter: A filter to select specific files from project's artifacts. """ project: str file_filter: Optional[str] = None @property - def endpoint(self) -> str: + def __releases_endpoint(self) -> str: """Formatted endpoint. :return: GitHub API endpoint for specified project's latest release. @@ -33,7 +33,7 @@ def endpoint(self) -> str: return f"https://api.github.com/repos/{self.project}/releases/latest" @property - def direct_url(self) -> str: + def __direct_url(self) -> str: """Direct URL to GitHub project. :return: URL to GitHub project. @@ -47,7 +47,7 @@ def run(self) -> str | None: :return: URL to download release artifact from if applicable. :rtype: str | None """ - response = requests.get(self.endpoint).json() + response = requests.get(self.__releases_endpoint).json() # check whether the GitHub API usage is exceeded try: @@ -81,12 +81,12 @@ def run(self) -> str | None: # if not available via API -- use regular "git clone" log.warning(f"Non-API GitHub resolution for {self.project}") - rdir = Path(dcfg.assets, self.direct_url.rsplit("/", 1)[1]) + rdir = Path(dcfg.assets, self.__direct_url.rsplit("/", 1)[1]) cm.remove(rdir) ccmd.launch( "git clone --depth 1 --remote-submodules --recurse-submodules --shallow-submodules {} {}" - .format(self.direct_url, rdir) + .format(self.__direct_url, rdir) ) os.chdir(rdir) cm.remove(".git*") diff --git a/zkb/clients/los.py b/zkb/clients/los.py index 713be0a..40a1edd 100644 --- a/zkb/clients/los.py +++ b/zkb/clients/los.py @@ -1,3 +1,4 @@ +from zkb.enums import EnumKernelBase from zkb.clients.rom_api import RomApiClient @@ -6,4 +7,4 @@ class LineageOsApiClient(RomApiClient): endpoint: str = "https://download.lineageos.org/api/v1/{}/nightly/ro.build.version.incremental" json_key: str = "response" - rom_name: str = "LOS" + rom_name: EnumKernelBase = EnumKernelBase.LOS diff --git a/zkb/clients/pa.py b/zkb/clients/pa.py index 6e3fb0c..a2d3595 100644 --- a/zkb/clients/pa.py +++ b/zkb/clients/pa.py @@ -1,5 +1,6 @@ from typing import override +from zkb.enums import EnumKernelBase from zkb.clients.rom_api import RomApiClient @@ -8,7 +9,7 @@ class ParanoidAndroidApiClient(RomApiClient): endpoint: str = "https://api.paranoidandroid.co/updates/{}" json_key: str = "updates" - rom_name: str = "PA" + rom_name: EnumKernelBase = EnumKernelBase.PA @override def map_codename(self) -> str: diff --git a/zkb/clients/rom_api.py b/zkb/clients/rom_api.py index a0e89f8..7edd7c9 100644 --- a/zkb/clients/rom_api.py +++ b/zkb/clients/rom_api.py @@ -2,6 +2,7 @@ import logging from zkb.configs import ModelConfig +from zkb.enums import EnumKernelBase from zkb.interfaces import IRomApiClient @@ -13,13 +14,13 @@ class RomApiClient(ModelConfig, IRomApiClient): :param str endpoint: API endpoint to interact with. :param str json_key: A JSON key to look for in the response data. - :param str rom_name: ROM project's name. + :param zkb.enums.EnumKernelBase rom_name: ROM project's name. :param bool rom_only: Flag indicating ROM-only asset collection. """ endpoint: str json_key: str - rom_name: str + rom_name: EnumKernelBase codename: str rom_only: bool @@ -38,6 +39,6 @@ def run(self) -> str: data = data.json()[self.json_key][0]["url"] except Exception: exit_flag = False if self.rom_only else True - log.error(f"Could not connect to {self.rom_name} API, HTTP status code: {data.status_code}") + log.error(f"Could not connect to {self.rom_name.value} API, HTTP status code: {data.status_code}") return str(data) diff --git a/zkb/commands/assets.py b/zkb/commands/assets.py index 792585b..aa9a2d0 100644 --- a/zkb/commands/assets.py +++ b/zkb/commands/assets.py @@ -13,7 +13,7 @@ class AssetsCommand(ModelConfig, ICommand): """Command responsible for launching the 'assets_collector' core module directly. - :param builder.core.AssetsCollector assets_collector: Assets collector object. + :param zkb.core.AssetsCollector assets_collector: Assets collector object. """ assets_collector: AssetsCollector diff --git a/zkb/commands/bundle.py b/zkb/commands/bundle.py index b5b4b1d..932b1b6 100644 --- a/zkb/commands/bundle.py +++ b/zkb/commands/bundle.py @@ -4,9 +4,10 @@ import logging import itertools from pathlib import Path -from typing import Literal, Optional +from typing import Optional, Iterable from zkb.core import KernelBuilder, AssetsCollector +from zkb.enums import EnumPackageType from zkb.tools import cleaning as cm, commands as ccmd, fileoperations as fo from zkb.configs import DirectoryConfig as dcfg, ModelConfig from zkb.interfaces import ICommand @@ -18,30 +19,30 @@ class BundleCommand(ModelConfig, ICommand): """Command that packages the artifacts produced both by 'kernel_builder' and 'assets_collector' core modules. - :param builder.core.KernelBuilder kernel_builder: Kernel builder object. - :param builder.core.AssetsCollector assets_collector: Assets collector object. + :param zkb.core.KernelBuilder kernel_builder: Kernel builder object. + :param zkb.core.AssetsCollector assets_collector: Assets collector object. :param str package_type: Package type. :param str base: ROM base for the kernel. """ kernel_builder: KernelBuilder assets_collector: AssetsCollector - package_type: str + package_type: Iterable[EnumPackageType] base: str - def build_kernel(self, rom_name: str, clean_only: Optional[bool] = False) -> None: + def build_kernel(self, clean_only: Optional[bool] = False) -> None: if not dcfg.kernel.is_dir() or clean_only is True: self.kernel_builder.clean_kernel = clean_only # type: ignore self.kernel_builder.run() @property - def _rom_only_flag(self) -> bool: - return True if "full" not in self.package_type else False + def __rom_only_flag(self) -> bool: + return True if EnumPackageType.FULL not in self.package_type else False - def collect_assets(self, rom_name: str, chroot: Literal["full", "minimal"]) -> None: + def collect_assets(self) -> None: self.assets_collector.clean_assets = True - self.assets_collector.rom_only = self._rom_only_flag + self.assets_collector.rom_only = self.__rom_only_flag self.assets_collector.run() @@ -107,11 +108,11 @@ def execute(self) -> None: # determine the bundle type and process it match self.package_type: - case "slim" | "full": - self.build_kernel(self.base) + case EnumPackageType.FULL | EnumPackageType.SLIM: + self.build_kernel() # "full" chroot is hardcoded here - self.collect_assets(self.base, "full") + self.collect_assets() # clean up if dcfg.bundle.is_dir(): @@ -130,7 +131,7 @@ def execute(self) -> None: # here, because of their size assets are moved and not copied shutil.move(dcfg.assets / afn, dcfg.bundle / afn) - case "conan": + case EnumPackageType.CONAN: # form Conan reference name = "zero_kernel" version = os.getenv("KVERSION") @@ -150,10 +151,10 @@ def execute(self) -> None: # build and upload Conan packages for opset in option_sets: - self.build_kernel(opset[0]) - self.build_kernel(opset[0], True) + self.build_kernel() + self.build_kernel(True) self.conan_sources() - self.collect_assets(opset[0], opset[1]) + self.collect_assets() self.conan_package(opset, reference) # upload packages diff --git a/zkb/commands/kernel.py b/zkb/commands/kernel.py index 639f4c7..0bf532a 100644 --- a/zkb/commands/kernel.py +++ b/zkb/commands/kernel.py @@ -12,7 +12,7 @@ class KernelCommand(ModelConfig, ICommand): """Command responsible for launching the 'kernel_builder' core module directly. - :param builder.core.KernelBuilder kernel_builder: Kernel builder object. + :param zkb.core.KernelBuilder kernel_builder: Kernel builder object. """ kernel_builder: KernelBuilder diff --git a/zkb/configs/argument.py b/zkb/configs/argument.py index 591c81d..57d8252 100644 --- a/zkb/configs/argument.py +++ b/zkb/configs/argument.py @@ -3,41 +3,44 @@ import logging import platform from pathlib import Path -from typing import Optional, Literal +from typing import Optional +from pydantic import BaseModel +from zkb.enums import EnumEnvironment, EnumCommand, EnumPackageType from zkb.tools import commands as ccmd -from zkb.configs import ModelConfig log = logging.getLogger("ZeroKernelLogger") -class ArgumentConfig(ModelConfig): +class ArgumentConfig(BaseModel): """Variable storage for usage across the app. - :param Literal["docker","podman","local"] benv: Build environment. - :param Literal["kernel","assets","bundle"] command: Builder command to be launched. + Only model not using shared ModelConfig. + + :param zkb.enums.EnumEnvironment benv: Build environment. + :param zkb.enums.EnumCommand command: Builder command to be launched. :param str codename: Device codename. :param str base: Kernel source base. :param str lkv: Linux kernel version. - :param Optional[str]=None chroot: Chroot type. - :param Optional[str]=None package_type: Package type. - :param Optional[bool]=False clean_kernel: Flag to clean folder with kernel sources. - :param Optional[bool]=False clean_assets: Flag to clean folder for assets storage. - :param Optional[bool]=False clean_image: Flag to clean a Docker/Podman image from local cache. - :param Optional[bool]=False rom_only: Flag indicating ROM-only asset collection. - :param Optional[bool]=False conan_upload: Flag to enable Conan upload. - :param Optional[bool]=False ksu: Flag indicating KernelSU support. - :param Optional[Path]=None defconfig: Path to custom defconfig. + :param typing.Optional[str]=None chroot: Chroot type. + :param typing.Optional[str]=None package_type: Package type. + :param typing.Optional[bool]=False clean_kernel: Flag to clean folder with kernel sources. + :param typing.Optional[bool]=False clean_assets: Flag to clean folder for assets storage. + :param typing.Optional[bool]=False clean_image: Flag to clean a Docker/Podman image from local cache. + :param typing.Optional[bool]=False rom_only: Flag indicating ROM-only asset collection. + :param typing.Optional[bool]=False conan_upload: Flag to enable Conan upload. + :param typing.Optional[bool]=False ksu: Flag indicating KernelSU support. + :param typing.Optional[Path]=None defconfig: Path to custom defconfig. """ - benv: Literal["docker", "podman", "local"] - command: Literal["kernel", "assets", "bundle"] + benv: EnumEnvironment + command: EnumCommand codename: str base: str lkv: Optional[str] = None chroot: Optional[str] = None - package_type: Optional[str] = None + package_type: Optional[EnumPackageType] = None clean_kernel: Optional[bool] = False clean_assets: Optional[bool] = False clean_image: Optional[bool] = False @@ -52,7 +55,7 @@ def check_settings(self) -> None: :return: None """ # allow only asset colletion on a non-Linux machine - if self.benv == "local" and self.command in {"kernel", "bundle"}: + if self.benv == EnumEnvironment.LOCAL and self.command in {EnumCommand.KERNEL, EnumCommand.BUNDLE}: if not platform.system() == "Linux": log.error("Can't build kernel on a non-Linux machine.") sys.exit(1) @@ -73,9 +76,9 @@ def check_settings(self) -> None: if self.codename not in devices.keys(): log.error("Unsupported device codename specified.") sys.exit(1) - if self.command == "bundle": + if self.command == EnumCommand.BUNDLE: # check Conan-related argument usage - if self.package_type != "conan" and self.conan_upload: + if self.package_type != EnumPackageType.CONAN and self.conan_upload: log.error("Cannot use Conan-related arguments with non-Conan packaging\n") sys.exit(1) diff --git a/zkb/configs/directory.py b/zkb/configs/directory.py index 50c2952..830c9b0 100644 --- a/zkb/configs/directory.py +++ b/zkb/configs/directory.py @@ -1,11 +1,13 @@ from pathlib import Path from pydantic.dataclasses import dataclass +from zkb.enums import EnumCommand + @dataclass class DirectoryConfig: """Config for key directory paths.""" root: Path = Path(__file__).absolute().parents[2] - kernel: Path = root / "kernel" - assets: Path = root / "assets" - bundle: Path = root / "bundle" + kernel: Path = root / EnumCommand.KERNEL.value + assets: Path = root / EnumCommand.ASSETS.value + bundle: Path = root / EnumCommand.BUNDLE.value diff --git a/zkb/core/assets_collector.py b/zkb/core/assets_collector.py index 9c64fc6..5603f5c 100644 --- a/zkb/core/assets_collector.py +++ b/zkb/core/assets_collector.py @@ -1,8 +1,9 @@ import os import sys import logging -from typing import Literal, Optional +from typing import Optional +from zkb.enums import EnumChroot, EnumKernelBase from zkb.tools import banner, fileoperations as fo, cleaning as cm from zkb.clients import GithubApiClient, LineageOsApiClient, ParanoidAndroidApiClient from zkb.configs import DirectoryConfig as dcfg, ModelConfig @@ -17,14 +18,14 @@ class AssetsCollector(ModelConfig, IAssetsCollector): :param str codename: Device codename. :param str base: Kernel source base. - :param Optional[Literal["full","minimal"]]=None chroot: Chroot type. + :param typing.Optional[zkb.enums.EnumChroot]=None chroot: Chroot type. :param bool rom_only: Flag indicating ROM-only asset collection. :param bool ksu: Flag indicating KernelSU support. """ codename: str base: str - chroot: Optional[Literal["full", "minimal"]] = None + chroot: Optional[EnumChroot] = None clean_assets: bool rom_only: bool ksu: bool @@ -32,11 +33,11 @@ class AssetsCollector(ModelConfig, IAssetsCollector): @property def rom_collector_dto(self) -> LineageOsApiClient | ParanoidAndroidApiClient | None: match self.base: - case "los": + case EnumKernelBase.LOS: return LineageOsApiClient(codename=self.codename, rom_only=self.rom_only) - case "pa": + case EnumKernelBase.PA: return ParanoidAndroidApiClient(codename=self.codename, rom_only=self.rom_only) - case "x" | "aosp": + case EnumKernelBase.X | EnumKernelBase.AOSP: # selected kernel base is ROM-universal, no specific ROM image will be collected return None diff --git a/zkb/core/kernel_builder.py b/zkb/core/kernel_builder.py index c4133a8..089b5cf 100644 --- a/zkb/core/kernel_builder.py +++ b/zkb/core/kernel_builder.py @@ -22,7 +22,7 @@ class KernelBuilder(ModelConfig, IKernelBuilder): :param str lkv: Linux kernel version. :param bool clean_kernel: Flag to clean folder with kernel sources. :param bool ksu: Flag indicating KernelSU support. - :param Optional[Path]=None defconfig: Path to custom defconfig. + :param typing.Optional[Path]=None defconfig: Path to custom defconfig. """ codename: str diff --git a/zkb/engines/generic_container.py b/zkb/engines/generic_container.py index 1af332e..1a4d557 100644 --- a/zkb/engines/generic_container.py +++ b/zkb/engines/generic_container.py @@ -6,6 +6,7 @@ from typing import Optional, Literal from subprocess import CompletedProcess +from zkb.enums import EnumChroot, EnumCommand, EnumContainerEnvironment, EnumPackageType from zkb.tools import commands as ccmd from zkb.configs import DirectoryConfig as dcfg, ModelConfig from zkb.interfaces import IGenericContainerEngine @@ -23,20 +24,20 @@ class GenericContainerEngine(ModelConfig, IGenericContainerEngine): directory structure. We don't need to pass full paths relevant to local environment, only directories' names. - :param Literal["docker","podman"] benv: Build environment. - :param Literal["kernel","assets","bundle"] command: Builder command to be launched. + :param zkb.enums.EnumEnvironment benv: Build environment. + :param zkb.enums.EnumCommand command: Builder command to be launched. :param str codename: Device codename. :param str base: Kernel source base. :param str lkv: Linux kernel version. - :param Optional[Literal["full","minimal"]]=None chroot: Chroot type. - :param Optional[bool]=False package_type: Package type. - :param Optional[bool]=False clean_kernel: Flag to clean folder for kernel storage. - :param Optional[bool]=False clean_assets: Flag to clean folder for assets storage. - :param Optional[bool]=False clean_image: Flag to clean a Docker/Podman image from local cache. - :param Optional[bool]=False rom_only: Flag indicating ROM-only asset collection. - :param Optional[bool]=False conan_upload: Flag to enable Conan upload. - :param Optional[bool]=False ksu: Flag to add KernelSU support into the kernel. - :param Optional[Path]=None defconfig: Path to custom defconfig. + :param typing.Optional[zkb.enums.EnumChroot]=None chroot: Chroot type. + :param typing.Optional[bool]=False package_type: Package type. + :param typing.Optional[bool]=False clean_kernel: Flag to clean folder for kernel storage. + :param typing.Optional[bool]=False clean_assets: Flag to clean folder for assets storage. + :param typing.Optional[bool]=False clean_image: Flag to clean a Docker/Podman image from local cache. + :param typing.Optional[bool]=False rom_only: Flag indicating ROM-only asset collection. + :param typing.Optional[bool]=False conan_upload: Flag to enable Conan upload. + :param typing.Optional[bool]=False ksu: Flag to add KernelSU support into the kernel. + :param typing.Optional[Path]=None defconfig: Path to custom defconfig. """ _name_image: str = "zero-kernel-image" @@ -44,12 +45,12 @@ class GenericContainerEngine(ModelConfig, IGenericContainerEngine): _wdir_container: Path = Path("/", "zero_build") _wdir_local: Path = dcfg.root - benv: Literal["docker", "podman"] - command: Literal["kernel", "assets", "bundle"] + benv: EnumContainerEnvironment + command: EnumCommand codename: str base: str lkv: Optional[str] = None - chroot: Optional[Literal["full", "minimal"]] = None + chroot: Optional[EnumChroot] = None package_type: Optional[str] = None clean_kernel: Optional[bool] = False clean_assets: Optional[bool] = False @@ -72,7 +73,7 @@ def dir_bundle_conan(self) -> Path: return Path(os.getenv("HOME"), ".conan") # type: ignore def check_cache(self) -> bool: - img_cache_cmd = f'{self.benv} images --format {"{{.Repository}}"}' + img_cache_cmd = f'{self.benv.value} image list --format {"{{.Repository}}"}' img_cache = str(ccmd.launch(img_cache_cmd, get_output=True)) return True if self._name_image in img_cache else False @@ -105,8 +106,8 @@ def builder_cmd(self) -> str: cmd += f" {arg}" # extend the command with the selected packaging option - if self.command == "bundle": - if self.package_type in ("slim", "full"): + if self.command == EnumCommand.BUNDLE: + if self.package_type in (EnumPackageType.SLIM, EnumPackageType.FULL): cmd += f" && chmod 777 -R {self._wdir_container / dcfg.bundle.name}" else: cmd += " && chmod 777 -R /root/.conan" @@ -129,15 +130,15 @@ def container_options(self) -> list[str]: # mount directories match self.command: - case "kernel": + case EnumCommand.KERNEL: options.append(v_template.format(dcfg.kernel, self._wdir_container, dcfg.kernel.name)) - case "assets": + case EnumCommand.ASSETS: options.append(v_template.format(dcfg.assets, self._wdir_container, dcfg.assets.name)) - case "bundle": + case EnumCommand.BUNDLE: match self.package_type: - case "slim" | "full": + case EnumPackageType.SLIM | EnumPackageType.FULL: options.append(v_template.format(dcfg.bundle, self._wdir_container, dcfg.bundle.name)) - case "conan": + case EnumPackageType.CONAN: if self.conan_upload: options.append("-e CONAN_UPLOAD_CUSTOM=1") # determine the path to local Conan cache and check if it exists @@ -151,26 +152,26 @@ def container_options(self) -> list[str]: def create_dirs(self) -> None: match self.command: - case "kernel": + case EnumCommand.KERNEL: if not dcfg.kernel.is_dir(): os.makedirs(dcfg.kernel) - case "assets": + case EnumCommand.ASSETS: if not dcfg.assets.is_dir(): os.makedirs(dcfg.assets) - case "bundle": - if self.package_type in ("slim", "full"): + case EnumCommand.BUNDLE: + if self.package_type in (EnumPackageType.SLIM, EnumPackageType.FULL): # mount directory with release artifacts shutil.rmtree(dcfg.bundle, ignore_errors=True) os.makedirs(dcfg.bundle) def build_image(self) -> str | None | CompletedProcess: print("\n") - log.warning(f"Building the {self.benv.capitalize()} image..") + log.warning(f"Building the {self.benv.value.capitalize()} image..") os.chdir(self._wdir_local) # NOTE: this will crash in GitLab CI/CD (Docker-in-Docker), requires a workaround cmd = "{} build . -f {} -t {} --load".format( - self.benv, + self.benv.value, self._wdir_local / "Dockerfile", self._name_image ) @@ -184,7 +185,7 @@ def build_image(self) -> str | None | CompletedProcess: @property def get_container_cmd(self) -> str: return '{} run {} {} /bin/bash -c "source .venv/bin/activate && {}"'.format( - self.benv, + self.benv.value, " ".join(self.container_options), self._name_image, self.builder_cmd @@ -192,14 +193,14 @@ def get_container_cmd(self) -> str: def __enter__(self) -> str: # prepare Docker if selected - if self.benv == "docker": + if self.benv == EnumContainerEnvironment.DOCKER: self._force_buildkit() # build the image and prepare directories if not self.check_cache(): self.build_image() else: - log.warning(f"{self.benv.capitalize()} image already in local cache, skipping it's build..\n") + log.warning(f"{self.benv.value.capitalize()} image already in local cache, skipping it's build..\n") self.create_dirs() return self.get_container_cmd @@ -209,4 +210,4 @@ def __exit__(self, exc_type, exc_value, traceback) -> None: os.chdir(self._wdir_local) if self.clean_image: - ccmd.launch(f"{self.benv} rmi {self._name_image}") + ccmd.launch(f"{self.benv.value} rmi {self._name_image}") diff --git a/zkb/enums.py b/zkb/enums.py new file mode 100644 index 0000000..d29927b --- /dev/null +++ b/zkb/enums.py @@ -0,0 +1,71 @@ +from enum import Enum + + +class EnumChroot(Enum): + FULL = "full" + MINIMAL = "minimal" + + @staticmethod + def from_string(s): + try: + return EnumCommand[s] + except KeyError: + raise ValueError() + + +class EnumCommand(Enum): + KERNEL = "kernel" + ASSETS = "assets" + BUNDLE = "bundle" + + @staticmethod + def from_string(s): + try: + return EnumCommand[s] + except KeyError: + raise ValueError() + + +class EnumContainerEnvironment(Enum): + DOCKER = "docker" + PODMAN = "podman" + + +class EnumEnvironment(Enum): + LOCAL = "local" + DOCKER = "docker" + PODMAN = "podman" + + @staticmethod + def from_string(s): + try: + return EnumCommand[s] + except KeyError: + raise ValueError() + + +class EnumPackageType(Enum): + CONAN = "conan" + SLIM = "slim" + FULL = "full" + + @staticmethod + def from_string(s): + try: + return EnumCommand[s] + except KeyError: + raise ValueError() + + +class EnumKernelBase(Enum): + LOS = "los" + PA = "pa" + X = "x" + AOSP = "aosp" + + @staticmethod + def from_string(s): + try: + return EnumCommand[s] + except KeyError: + raise ValueError() diff --git a/zkb/managers/resource.py b/zkb/managers/resource.py index 9eea5c1..74531ed 100644 --- a/zkb/managers/resource.py +++ b/zkb/managers/resource.py @@ -17,9 +17,9 @@ class ResourceManager(ModelConfig, IResourceManager): """Build resource manager. - :param Optional[str]=None codename: Device codename. - :param Optional[str]=None base: Kernel source base. - :param Optional[str]=None lkv: Linux kernel version. + :param typing.Optional[str]=None codename: Device codename. + :param typing.Optional[str]=None base: Kernel source base. + :param typing.Optional[str]=None lkv: Linux kernel version. """ _data: dict[str, dict[str, str]] = {} diff --git a/zkb/tools/cleaning.py b/zkb/tools/cleaning.py index f197d35..039503b 100644 --- a/zkb/tools/cleaning.py +++ b/zkb/tools/cleaning.py @@ -15,7 +15,7 @@ def remove(elements: str | Path | list[Path | str]) -> None: Here, all Path() objects will have to be converted into str. Because of such specific as directories starting with a "." (e.g., .github). - :param str/Path/list[Path] elements: Files and/or directories to remove. + :param str/pathlib.Path/list[pathlib.Path] elements: Files and/or directories to remove. :return: None """ # if a given argument is a string --> convert it into a one-element list @@ -43,7 +43,7 @@ def on_rm_error(func, path: str, exc_info): """For Windows system to remove a .git folder. :param func: Function to be used along with. - :param Path path: Path that is being removed. + :param pathlib.Path path: Path that is being removed. :exc_info param: Misc info. """ os.chmod(path, stat.S_IWRITE) @@ -53,7 +53,7 @@ def on_rm_error(func, path: str, exc_info): def git(directory: Path | str) -> None: """Clean up a git directory. - :param Path/str directory: Path to the directory. + :param pathlib.Path/str directory: Path to the directory. """ goback = Path.cwd() @@ -66,7 +66,7 @@ def git(directory: Path | str) -> None: def root(extra: Optional[list[str]] = []) -> None: """Fully clean the root directory. - :param Optional[list[str]]=[] extra: Extra elements to be removed. + :param typing.Optional[list[str]]=[] extra: Extra elements to be removed. """ trsh = [ dcfg.kernel, diff --git a/zkb/tools/commands.py b/zkb/tools/commands.py index 0a62565..3577d33 100644 --- a/zkb/tools/commands.py +++ b/zkb/tools/commands.py @@ -17,8 +17,8 @@ def launch( """Custom subprocess wrapper to launch commands. :param str cmd: Command to launch. - :param Optional[bool]=False get_output: Switch to get the piped output of the command. - :param str loglvl: Log level. + :param typing.Optional[bool]=False get_output: Switch to get the piped output of the command. + :param typing.Optional[Literal["normal", "quiet"]] loglvl: Log level. :return: Result of command launch. :rtype: str | CompletedProcess | None """ diff --git a/zkb/tools/fileoperations.py b/zkb/tools/fileoperations.py index 367c55b..5afa543 100644 --- a/zkb/tools/fileoperations.py +++ b/zkb/tools/fileoperations.py @@ -15,9 +15,9 @@ def ucopy(src: Path, dst: Path, exceptions: Optional[tuple[str | Path, ...]] = ()) -> None: """Copy files and directories into desired destinations universally. - :param Path src: Source path. - :param Path dst: Destination path. - :param Optional[tuple[str/Path,...]]=() exceptions: Elements that will not be removed. + :param pathlib.Path src: Source path. + :param pathlib.Path dst: Destination path. + :param typing.Optional[tuple[str/pathlib.Path,...]]=() exceptions: Elements that will not be removed. :return: None """ # for a directory (it's contents) @@ -99,7 +99,7 @@ def replace_lines(filename: Path, og_lines: tuple[str, ...], nw_lines: tuple[str def replace_nth(filename: Path, og_string: str, nw_string: str, occurence: int) -> None: """Replace the n-th occurence of subtring in specified file. - :param Path filename: Path to the filename. + :param pathlib.Path filename: Path to the filename. :param str og_string: Original string to be replaced. :param str nw_string: New string used to replace the original one. :param int occurence: The index of occurence to replace. @@ -124,7 +124,7 @@ def replace_nth(filename: Path, og_string: str, nw_string: str, occurence: int) def insert_before_line(filename: str | Path, pointer_line: str, new_line: str) -> None: """Insert new line before the specified one. - :param str/Path filename: Name of the file. + :param str/pathlib.Path filename: Name of the file. :param str pointer_line: The line before which new line will be inserted. :param str new_line: The line being inserted. :return: None @@ -149,7 +149,7 @@ def insert_before_line(filename: str | Path, pointer_line: str, new_line: str) - def apply_patch(filename: str | Path) -> None: """Apply .patch file. - :param str/Path filename: Name of the .patch file. + :param str/pathlib.Path filename: Name of the .patch file. :return: None """ log.warning(f"Applying patch: {filename}") diff --git a/zkb/utils/bridge.py b/zkb/utils/bridge.py index 6221147..fb2cfa6 100644 --- a/zkb/utils/bridge.py +++ b/zkb/utils/bridge.py @@ -10,6 +10,7 @@ import argparse from zkb.core import KernelBuilder, AssetsCollector +from zkb.enums import EnumCommand, EnumPackageType, EnumChroot from zkb.managers import ResourceManager from zkb.commands import KernelCommand, AssetsCommand, BundleCommand @@ -35,8 +36,9 @@ def parse_args() -> argparse.Namespace: parser = argparse.ArgumentParser() parser.add_argument( "--command", + type=EnumCommand.from_string, help="select builder command", - choices={"kernel", "assets", "bundle"} + choices=tuple(EnumCommand) ) parser.add_argument( "--codename", @@ -52,14 +54,16 @@ def parse_args() -> argparse.Namespace: ) parser.add_argument( "--chroot", + type=EnumChroot.from_string, + choices=tuple(EnumChroot), help="select chroot type", - choices={"full", "minimal"} ) parser.add_argument( "--package-type", dest="package_type", - help="select bundle packaging type", - choices={"conan", "slim", "full"} + type=EnumPackageType.from_string, + choices=tuple(EnumPackageType), + help="select bundle packaging type" ) parser.add_argument( "--clean-kernel", @@ -99,10 +103,8 @@ def parse_args() -> argparse.Namespace: def main(args: argparse.Namespace) -> None: - match args.command: - - case "kernel": + case EnumCommand.KERNEL: kernel_builder = KernelBuilder( codename = args.codename, base = args.base, @@ -119,7 +121,7 @@ def main(args: argparse.Namespace) -> None: kc = KernelCommand(kernel_builder=kernel_builder) kc.execute() - case "assets": + case EnumCommand.ASSETS: assets_collector = AssetsCollector( codename = args.codename, base = args.base, @@ -131,7 +133,7 @@ def main(args: argparse.Namespace) -> None: ac = AssetsCommand(assets_collector=assets_collector) ac.execute() - case "bundle": + case EnumCommand.BUNDLE: kernel_builder = KernelBuilder( codename = args.codename, base = args.base, From a48a46bb53705c111a056b9f446c2ee819a35d5f Mon Sep 17 00:00:00 2001 From: Joseph Date: Sat, 28 Feb 2026 17:26:07 +0100 Subject: [PATCH 08/19] docs: update README --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e87ec6a..f85ddba 100755 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ -# zero_kernel +# zero-kernel An advanced Android kernel builder with assets collection and Kali NetHunter support. ## Contents -- [zero\_kernel](#zero_kernel) +- [zero-kernel](#zero-kernel) - [Contents](#contents) - [**Important**](#important) - [Description](#description) From 0b04a39ded9b1610d3090cb6e5e0f15a079508e5 Mon Sep 17 00:00:00 2001 From: Joseph Date: Sat, 28 Feb 2026 18:31:57 +0100 Subject: [PATCH 09/19] chore: remove unused import --- zkb/__main__.py | 1 - 1 file changed, 1 deletion(-) diff --git a/zkb/__main__.py b/zkb/__main__.py index 34a9969..02b74aa 100644 --- a/zkb/__main__.py +++ b/zkb/__main__.py @@ -1,4 +1,3 @@ -from enum import EnumType import os import io import sys From 3afb007c64b4548c942417fe9eb6ed2c5e34f031 Mon Sep 17 00:00:00 2001 From: Joseph Date: Sat, 28 Feb 2026 21:08:15 +0100 Subject: [PATCH 10/19] chore: update metainfo --- conanfile.py | 2 +- pyproject.toml | 4 ++-- zkb/__main__.py | 2 +- zkb/commands/bundle.py | 2 +- zkb/core/kernel_builder.py | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/conanfile.py b/conanfile.py index 23c3ff3..8006ab6 100644 --- a/conanfile.py +++ b/conanfile.py @@ -6,7 +6,7 @@ class ZeroKernelConan(ConanFile): author = "seppzer0" url = "https://gitlab.com/api/v4/projects/40803264/packages/conan" description = "An advanced Android kernel builder with Kali NetHunter support." - topics = ("zero_kernel", "kali-nethunter", "nethunter") + topics = ("zero-kernel", "kali-nethunter", "nethunter") settings = None options = { "base": {"los", "pa", "x", "aosp"}, diff --git a/pyproject.toml b/pyproject.toml index 079f8d0..65f78b3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,8 +7,8 @@ readme = "README.md" requires-python = ">=3.12" [project.urls] -Repository = "https://github.com/seppzer0/zero_kernel" -Documentation = "https://github.com/seppzer0/zero_kernel/blob/main/README.md" +Repository = "https://github.com/seppzer0/zero-kernel" +Documentation = "https://github.com/seppzer0/zero-kernel/blob/main/README.md" [project.scripts] zkb = "zkb.__main__:main" diff --git a/zkb/__main__.py b/zkb/__main__.py index 02b74aa..8bfc4e6 100644 --- a/zkb/__main__.py +++ b/zkb/__main__.py @@ -28,7 +28,7 @@ def __get_version() -> str: :return: App version. :rtype: str """ - msg = "zero_kernel {}" + msg = "zero-kernel {}" try: return msg.format(version("zero-kernel")) diff --git a/zkb/commands/bundle.py b/zkb/commands/bundle.py index 932b1b6..896fbec 100644 --- a/zkb/commands/bundle.py +++ b/zkb/commands/bundle.py @@ -133,7 +133,7 @@ def execute(self) -> None: case EnumPackageType.CONAN: # form Conan reference - name = "zero_kernel" + name = "zero-kernel" version = os.getenv("KVERSION") user = self.kernel_builder.codename channel = "" diff --git a/zkb/core/kernel_builder.py b/zkb/core/kernel_builder.py index 089b5cf..a033c0d 100644 --- a/zkb/core/kernel_builder.py +++ b/zkb/core/kernel_builder.py @@ -36,7 +36,7 @@ class KernelBuilder(ModelConfig, IKernelBuilder): @staticmethod def write_localversion() -> None: with open("localversion", "w", encoding="utf-8") as f: - f.write("~zero_kernel") + f.write("~zero-kernel") @property def _ucodename(self) -> str: From 8281e25ca8580f6c25174cb4cfd5d6c677fd830c Mon Sep 17 00:00:00 2001 From: Joseph Date: Sun, 1 Mar 2026 20:14:26 +0100 Subject: [PATCH 11/19] chore: remove unused symbol --- zkb/__main__.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/zkb/__main__.py b/zkb/__main__.py index 8bfc4e6..8d85396 100644 --- a/zkb/__main__.py +++ b/zkb/__main__.py @@ -8,8 +8,6 @@ from pathlib import Path from importlib.metadata import version -from pydantic.types import PastDate - from zkb.core import KernelBuilder, AssetsCollector from zkb.tools import cleaning as cm, commands as ccmd, Logger as logger from zkb.enums import EnumChroot, EnumCommand, EnumEnvironment, EnumContainerEnvironment, EnumKernelBase, EnumPackageType From 248e866f2430f98dd40dbbb4509f5e60cb5040e1 Mon Sep 17 00:00:00 2001 From: Joseph Date: Sun, 1 Mar 2026 20:24:14 +0100 Subject: [PATCH 12/19] chore: adjust builder version --- pyproject.toml | 2 +- uv.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 65f78b3..1d9b285 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "zero-kernel-builder" -version = "0.7.0" +version = "0.6.5" description = "Advanced Android kernel builder with Kali NetHunter support." authors = [{name = "seppzer0"}] readme = "README.md" diff --git a/uv.lock b/uv.lock index e8a8078..f2479bb 100644 --- a/uv.lock +++ b/uv.lock @@ -257,11 +257,11 @@ wheels = [ [[package]] name = "filelock" -version = "3.24.3" +version = "3.25.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/73/92/a8e2479937ff39185d20dd6a851c1a63e55849e447a55e798cc2e1f49c65/filelock-3.24.3.tar.gz", hash = "sha256:011a5644dc937c22699943ebbfc46e969cdde3e171470a6e40b9533e5a72affa", size = 37935, upload-time = "2026-02-19T00:48:20.543Z" } +sdist = { url = "https://files.pythonhosted.org/packages/77/18/a1fd2231c679dcb9726204645721b12498aeac28e1ad0601038f94b42556/filelock-3.25.0.tar.gz", hash = "sha256:8f00faf3abf9dc730a1ffe9c354ae5c04e079ab7d3a683b7c32da5dd05f26af3", size = 40158, upload-time = "2026-03-01T15:08:45.916Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/9c/0f/5d0c71a1aefeb08efff26272149e07ab922b64f46c63363756224bd6872e/filelock-3.24.3-py3-none-any.whl", hash = "sha256:426e9a4660391f7f8a810d71b0555bce9008b0a1cc342ab1f6947d37639e002d", size = 24331, upload-time = "2026-02-19T00:48:18.465Z" }, + { url = "https://files.pythonhosted.org/packages/f9/0b/de6f54d4a8bedfe8645c41497f3c18d749f0bd3218170c667bf4b81d0cdd/filelock-3.25.0-py3-none-any.whl", hash = "sha256:5ccf8069f7948f494968fc0713c10e5c182a9c9d9eef3a636307a20c2490f047", size = 26427, upload-time = "2026-03-01T15:08:44.593Z" }, ] [[package]] @@ -826,7 +826,7 @@ wheels = [ [[package]] name = "zero-kernel-builder" -version = "0.7.0" +version = "0.6.5" source = { editable = "." } [package.dev-dependencies] From 60645d4689c0d0c6498f33ac6c6ab837b96c1d2a Mon Sep 17 00:00:00 2001 From: Joseph Date: Sun, 1 Mar 2026 20:30:44 +0100 Subject: [PATCH 13/19] docs: update dosctrings and architecture docs --- docs/architecture/clients/classes.puml | 8 +++----- docs/architecture/commands/classes.puml | 14 +++++++------- docs/architecture/configs/classes.puml | 9 ++++++--- docs/architecture/configs/packages.puml | 3 +++ docs/architecture/core/classes.puml | 4 ++-- docs/architecture/engines/classes.puml | 6 +++--- zkb/configs/argument.py | 2 +- zkb/engines/generic_container.py | 2 +- 8 files changed, 26 insertions(+), 22 deletions(-) diff --git a/docs/architecture/clients/classes.puml b/docs/architecture/clients/classes.puml index 54b22ea..6ebc4a3 100644 --- a/docs/architecture/clients/classes.puml +++ b/docs/architecture/clients/classes.puml @@ -1,8 +1,6 @@ @startuml classes set namespaceSeparator none class "GithubApiClient" as clients.github.GithubApiClient { - direct_url : str - endpoint : str file_filter : Optional[str] project : str run() -> str | None @@ -10,19 +8,19 @@ class "GithubApiClient" as clients.github.GithubApiClient { class "LineageOsApiClient" as clients.los.LineageOsApiClient { endpoint : str json_key : str - rom_name : str + rom_name } class "ParanoidAndroidApiClient" as clients.pa.ParanoidAndroidApiClient { endpoint : str json_key : str - rom_name : str + rom_name map_codename() -> str } class "RomApiClient" as clients.rom_api.RomApiClient { codename : str endpoint : str json_key : str - rom_name : str + rom_name rom_only : bool map_codename() -> str run() -> str diff --git a/docs/architecture/commands/classes.puml b/docs/architecture/commands/classes.puml index 61fe861..28d0f99 100644 --- a/docs/architecture/commands/classes.puml +++ b/docs/architecture/commands/classes.puml @@ -1,16 +1,16 @@ @startuml classes set namespaceSeparator none class "AssetsCommand" as commands.assets.AssetsCommand { - assets_collector : AssetsCollector + assets_collector execute() -> None } class "BundleCommand" as commands.bundle.BundleCommand { - assets_collector : AssetsCollector + assets_collector base : str - kernel_builder : KernelBuilder - package_type : str - build_kernel(rom_name: str, clean_only: Optional[bool]) -> None - collect_assets(rom_name: str, chroot: Literal['full', 'minimal']) -> None + kernel_builder + package_type : Iterable[EnumPackageType] + build_kernel(clean_only: Optional[bool]) -> None + collect_assets() -> None conan_options(json_file: str) -> dict conan_package(options: tuple[str, ...], reference: str) -> None conan_sources() -> None @@ -18,7 +18,7 @@ class "BundleCommand" as commands.bundle.BundleCommand { execute() -> None } class "KernelCommand" as commands.kernel.KernelCommand { - kernel_builder : KernelBuilder + kernel_builder execute() -> None } @enduml diff --git a/docs/architecture/configs/classes.puml b/docs/architecture/configs/classes.puml index 4f4bfcb..d117471 100644 --- a/docs/architecture/configs/classes.puml +++ b/docs/architecture/configs/classes.puml @@ -2,18 +2,18 @@ set namespaceSeparator none class "ArgumentConfig" as configs.argument.ArgumentConfig { base : str - benv : Literal['docker', 'podman', 'local'] + benv chroot : Optional[str] clean_assets : Optional[bool] clean_image : Optional[bool] clean_kernel : Optional[bool] codename : str - command : Literal['kernel', 'assets', 'bundle'] + command conan_upload : Optional[bool] defconfig : Optional[Path] ksu : Optional[bool] lkv : Optional[str] - package_type : Optional[str] + package_type : Optional[EnumPackageType] rom_only : Optional[bool] check_settings() -> None } @@ -23,4 +23,7 @@ class "DirectoryConfig" as configs.directory.DirectoryConfig { kernel : Path root : Path } +class "ModelConfig" as configs.model.ModelConfig { + model_config +} @enduml diff --git a/docs/architecture/configs/packages.puml b/docs/architecture/configs/packages.puml index c3101df..54ab3ff 100644 --- a/docs/architecture/configs/packages.puml +++ b/docs/architecture/configs/packages.puml @@ -6,6 +6,9 @@ package "configs.argument" as configs.argument { } package "configs.directory" as configs.directory { } +package "configs.model" as configs.model { +} configs --> configs.argument configs --> configs.directory +configs --> configs.model @enduml diff --git a/docs/architecture/core/classes.puml b/docs/architecture/core/classes.puml index cd8cbb4..fa46937 100644 --- a/docs/architecture/core/classes.puml +++ b/docs/architecture/core/classes.puml @@ -3,7 +3,7 @@ set namespaceSeparator none class "AssetsCollector" as core.assets_collector.AssetsCollector { assets : list base : str - chroot : Optional[Literal['full', 'minimal']] + chroot : Optional[EnumChroot] clean_assets : bool codename : str ksu : bool @@ -20,7 +20,7 @@ class "KernelBuilder" as core.kernel_builder.KernelBuilder { ksu : bool lkv : str lkv_src : str - rmanager : ResourceManager + rmanager build() -> None clean_build() -> None create_zip() -> None diff --git a/docs/architecture/engines/classes.puml b/docs/architecture/engines/classes.puml index 4b0a7bb..f1e5e81 100644 --- a/docs/architecture/engines/classes.puml +++ b/docs/architecture/engines/classes.puml @@ -2,14 +2,14 @@ set namespaceSeparator none class "GenericContainerEngine" as engines.generic_container.GenericContainerEngine { base : str - benv : Literal['docker', 'podman'] + benv builder_cmd : str - chroot : Optional[Literal['full', 'minimal']] + chroot : Optional[EnumChroot] clean_assets : Optional[bool] clean_image : Optional[bool] clean_kernel : Optional[bool] codename : str - command : Literal['kernel', 'assets', 'bundle'] + command conan_upload : Optional[bool] container_options : list[str] defconfig : Optional[Path] diff --git a/zkb/configs/argument.py b/zkb/configs/argument.py index 57d8252..aa3c425 100644 --- a/zkb/configs/argument.py +++ b/zkb/configs/argument.py @@ -31,7 +31,7 @@ class ArgumentConfig(BaseModel): :param typing.Optional[bool]=False rom_only: Flag indicating ROM-only asset collection. :param typing.Optional[bool]=False conan_upload: Flag to enable Conan upload. :param typing.Optional[bool]=False ksu: Flag indicating KernelSU support. - :param typing.Optional[Path]=None defconfig: Path to custom defconfig. + :param typing.Optional[pathlib.Path]=None defconfig: Path to custom defconfig. """ benv: EnumEnvironment diff --git a/zkb/engines/generic_container.py b/zkb/engines/generic_container.py index 1a4d557..9583a3f 100644 --- a/zkb/engines/generic_container.py +++ b/zkb/engines/generic_container.py @@ -37,7 +37,7 @@ class GenericContainerEngine(ModelConfig, IGenericContainerEngine): :param typing.Optional[bool]=False rom_only: Flag indicating ROM-only asset collection. :param typing.Optional[bool]=False conan_upload: Flag to enable Conan upload. :param typing.Optional[bool]=False ksu: Flag to add KernelSU support into the kernel. - :param typing.Optional[Path]=None defconfig: Path to custom defconfig. + :param typing.Optional[pathlib.Path]=None defconfig: Path to custom defconfig. """ _name_image: str = "zero-kernel-image" From becb529e621b0f71e53df5effdd5a5a514723315 Mon Sep 17 00:00:00 2001 From: Joseph Date: Mon, 2 Mar 2026 01:41:55 +0100 Subject: [PATCH 14/19] fix: update enum usage in args --- zkb/__main__.py | 8 ++++---- zkb/enums.py | 50 ++++++++++++++------------------------------- zkb/utils/bridge.py | 6 +++--- 3 files changed, 22 insertions(+), 42 deletions(-) diff --git a/zkb/__main__.py b/zkb/__main__.py index 8d85396..12eb3ab 100644 --- a/zkb/__main__.py +++ b/zkb/__main__.py @@ -76,7 +76,7 @@ def parse_args() -> argparse.Namespace: "config": { "required": True, "dest": "benv", - "type": EnumEnvironment.from_string, + "type": EnumEnvironment, "choices": tuple(EnumEnvironment), "help": "build environment" } @@ -86,7 +86,7 @@ def parse_args() -> argparse.Namespace: "config": { "required": True, "dest": "base", - "type": EnumKernelBase.from_string, + "type": EnumKernelBase, "choices": tuple(EnumKernelBase), "help": "kernel source base" } @@ -177,10 +177,10 @@ def parse_args() -> argparse.Namespace: parser_bundle.add_argument(*common_clean_image["name_or_flags"], **common_clean_image["config"]) parser_bundle.add_argument( "--package-type", - type=str, + type=EnumPackageType, required=True, dest="package_type", - choices=EnumPackageType, + choices=tuple(EnumPackageType), help="select package type of the bundle" ) parser_bundle.add_argument( diff --git a/zkb/enums.py b/zkb/enums.py index d29927b..175d9d0 100644 --- a/zkb/enums.py +++ b/zkb/enums.py @@ -1,29 +1,21 @@ from enum import Enum -class EnumChroot(Enum): +class EnumChroot(str, Enum): FULL = "full" MINIMAL = "minimal" - @staticmethod - def from_string(s): - try: - return EnumCommand[s] - except KeyError: - raise ValueError() + def __str__(self): + return self.value -class EnumCommand(Enum): +class EnumCommand(str, Enum): KERNEL = "kernel" ASSETS = "assets" BUNDLE = "bundle" - @staticmethod - def from_string(s): - try: - return EnumCommand[s] - except KeyError: - raise ValueError() + def __str__(self): + return self.value class EnumContainerEnvironment(Enum): @@ -31,41 +23,29 @@ class EnumContainerEnvironment(Enum): PODMAN = "podman" -class EnumEnvironment(Enum): +class EnumEnvironment(str, Enum): LOCAL = "local" DOCKER = "docker" PODMAN = "podman" - @staticmethod - def from_string(s): - try: - return EnumCommand[s] - except KeyError: - raise ValueError() + def __str__(self): + return self.value -class EnumPackageType(Enum): +class EnumPackageType(str, Enum): CONAN = "conan" SLIM = "slim" FULL = "full" - @staticmethod - def from_string(s): - try: - return EnumCommand[s] - except KeyError: - raise ValueError() + def __str__(self): + return self.value -class EnumKernelBase(Enum): +class EnumKernelBase(str, Enum): LOS = "los" PA = "pa" X = "x" AOSP = "aosp" - @staticmethod - def from_string(s): - try: - return EnumCommand[s] - except KeyError: - raise ValueError() + def __str__(self): + return self.value diff --git a/zkb/utils/bridge.py b/zkb/utils/bridge.py index fb2cfa6..bb068c8 100644 --- a/zkb/utils/bridge.py +++ b/zkb/utils/bridge.py @@ -36,7 +36,7 @@ def parse_args() -> argparse.Namespace: parser = argparse.ArgumentParser() parser.add_argument( "--command", - type=EnumCommand.from_string, + type=EnumCommand, help="select builder command", choices=tuple(EnumCommand) ) @@ -54,14 +54,14 @@ def parse_args() -> argparse.Namespace: ) parser.add_argument( "--chroot", - type=EnumChroot.from_string, + type=EnumChroot, choices=tuple(EnumChroot), help="select chroot type", ) parser.add_argument( "--package-type", dest="package_type", - type=EnumPackageType.from_string, + type=EnumPackageType, choices=tuple(EnumPackageType), help="select bundle packaging type" ) From 7d1461b3ca675cc2ae6e020f83312ee9e65f0b0d Mon Sep 17 00:00:00 2001 From: Joseph Date: Mon, 2 Mar 2026 02:00:52 +0100 Subject: [PATCH 15/19] fix: update enum configs --- zkb/__main__.py | 4 ++-- zkb/engines/generic_container.py | 6 +++--- zkb/enums.py | 15 +++++---------- 3 files changed, 10 insertions(+), 15 deletions(-) diff --git a/zkb/__main__.py b/zkb/__main__.py index 12eb3ab..eafe6cd 100644 --- a/zkb/__main__.py +++ b/zkb/__main__.py @@ -10,7 +10,7 @@ from zkb.core import KernelBuilder, AssetsCollector from zkb.tools import cleaning as cm, commands as ccmd, Logger as logger -from zkb.enums import EnumChroot, EnumCommand, EnumEnvironment, EnumContainerEnvironment, EnumKernelBase, EnumPackageType +from zkb.enums import EnumChroot, EnumCommand, EnumEnvironment, EnumKernelBase, EnumPackageType from zkb.configs import ArgumentConfig, DirectoryConfig as dcfg from zkb.engines import GenericContainerEngine from zkb.commands import KernelCommand, AssetsCommand, BundleCommand @@ -218,7 +218,7 @@ def main() -> None: # determine the build variation match args.benv: - case EnumContainerEnvironment.DOCKER | EnumContainerEnvironment.PODMAN: + case EnumEnvironment.DOCKER | EnumEnvironment.PODMAN: with GenericContainerEngine(**json.loads(acfg.model_dump_json())) as engined_cmd: ccmd.launch(engined_cmd) diff --git a/zkb/engines/generic_container.py b/zkb/engines/generic_container.py index 9583a3f..f4dc9b1 100644 --- a/zkb/engines/generic_container.py +++ b/zkb/engines/generic_container.py @@ -6,7 +6,7 @@ from typing import Optional, Literal from subprocess import CompletedProcess -from zkb.enums import EnumChroot, EnumCommand, EnumContainerEnvironment, EnumPackageType +from zkb.enums import EnumChroot, EnumCommand, EnumEnvironment, EnumPackageType from zkb.tools import commands as ccmd from zkb.configs import DirectoryConfig as dcfg, ModelConfig from zkb.interfaces import IGenericContainerEngine @@ -45,7 +45,7 @@ class GenericContainerEngine(ModelConfig, IGenericContainerEngine): _wdir_container: Path = Path("/", "zero_build") _wdir_local: Path = dcfg.root - benv: EnumContainerEnvironment + benv: EnumEnvironment command: EnumCommand codename: str base: str @@ -193,7 +193,7 @@ def get_container_cmd(self) -> str: def __enter__(self) -> str: # prepare Docker if selected - if self.benv == EnumContainerEnvironment.DOCKER: + if self.benv == EnumEnvironment.DOCKER: self._force_buildkit() # build the image and prepare directories diff --git a/zkb/enums.py b/zkb/enums.py index 175d9d0..deed6be 100644 --- a/zkb/enums.py +++ b/zkb/enums.py @@ -1,7 +1,7 @@ from enum import Enum -class EnumChroot(str, Enum): +class EnumChroot(Enum): FULL = "full" MINIMAL = "minimal" @@ -9,7 +9,7 @@ def __str__(self): return self.value -class EnumCommand(str, Enum): +class EnumCommand(Enum): KERNEL = "kernel" ASSETS = "assets" BUNDLE = "bundle" @@ -18,12 +18,7 @@ def __str__(self): return self.value -class EnumContainerEnvironment(Enum): - DOCKER = "docker" - PODMAN = "podman" - - -class EnumEnvironment(str, Enum): +class EnumEnvironment(Enum): LOCAL = "local" DOCKER = "docker" PODMAN = "podman" @@ -32,7 +27,7 @@ def __str__(self): return self.value -class EnumPackageType(str, Enum): +class EnumPackageType(Enum): CONAN = "conan" SLIM = "slim" FULL = "full" @@ -41,7 +36,7 @@ def __str__(self): return self.value -class EnumKernelBase(str, Enum): +class EnumKernelBase(Enum): LOS = "los" PA = "pa" X = "x" From 9f94872c2873b95ea134598f3f94591620526626 Mon Sep 17 00:00:00 2001 From: Joseph Date: Mon, 2 Mar 2026 02:07:39 +0100 Subject: [PATCH 16/19] ci: update uv version file --- .github/workflows/main.yml | 4 ++-- .gitlab-ci.yml | 2 +- Dockerfile | 2 +- README.md | 2 +- requirement-uv.txt => uv-version.txt | 0 5 files changed, 5 insertions(+), 5 deletions(-) rename requirement-uv.txt => uv-version.txt (100%) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index aa06060..2373a48 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -32,7 +32,7 @@ jobs: - name: Install UV run: | - UV_VERSION=$(cat ./requirement-uv.txt | awk -F'==' '{print $2}' | tr -d ' \n') + UV_VERSION=$(cat ./uv-version.txt | tr -d ' \n') curl -LsSf https://astral.sh/uv/${UV_VERSION}/install.sh | sh - name: Record original PATH @@ -80,7 +80,7 @@ jobs: - name: Install UV run: | - UV_VERSION=$(cat ./requirement-uv.txt | awk -F'==' '{print $2}' | tr -d ' \n') + UV_VERSION=$(cat ./uv-version.txt | tr -d ' \n') curl -LsSf https://astral.sh/uv/${UV_VERSION}/install.sh | sh - name: Get Current Version diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 1d3e452..cfff8f8 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -12,7 +12,7 @@ job-build: - docker:dind script: - apk update && apk add python3 py3-pip - - python3 -m pip install -r requirement-uv.txt --break-system-packages + - python3 -m pip install uv==$(cat ./uv-version.txt | tr -d ' \n') --break-system-packages - uv sync --frozen --no-install-project - source .venv/bin/activate - export PYTHONPATH=$(pwd) diff --git a/Dockerfile b/Dockerfile index 52d32af..8a53612 100755 --- a/Dockerfile +++ b/Dockerfile @@ -34,7 +34,7 @@ RUN \ # This significantly reduces the total build time, as each time we make a build call for a device, # only device-specific kernel source is being downloaded into the container. # -RUN curl -LsSf https://astral.sh/uv/$(cat ./requirement-uv.txt | awk -F'==' '{print $2}' | tr -d ' \n')/install.sh | sh && \ +RUN curl -LsSf https://astral.sh/uv/$(cat ./uv-version.txt | tr -d ' \n')/install.sh | sh && \ . $HOME/.local/bin/env && \ uv sync --frozen --no-install-project && \ uv run ${WDIR}/zkb/utils/bridge.py --shared diff --git a/README.md b/README.md index f85ddba..c7d142b 100755 --- a/README.md +++ b/README.md @@ -123,7 +123,7 @@ To run this tool in a `local` environment, you will need: ```sh # install uv version from project file -python3 -m pip install -r requirement-uv.txt +python3 -m pip install uv==$(cat ./uv-version.txt | tr -d ' \n') # make zkb/ internal imports visible to itself export PYTHONPATH=$(pwd) # prepare and activate dev environment diff --git a/requirement-uv.txt b/uv-version.txt similarity index 100% rename from requirement-uv.txt rename to uv-version.txt From 6881adafdbd58ce799714b9ed5c604caf004b580 Mon Sep 17 00:00:00 2001 From: Joseph Date: Mon, 2 Mar 2026 17:59:24 +0100 Subject: [PATCH 17/19] fix: wire enums in bridge --- zkb/utils/bridge.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/zkb/utils/bridge.py b/zkb/utils/bridge.py index bb068c8..614123b 100644 --- a/zkb/utils/bridge.py +++ b/zkb/utils/bridge.py @@ -10,7 +10,7 @@ import argparse from zkb.core import KernelBuilder, AssetsCollector -from zkb.enums import EnumCommand, EnumPackageType, EnumChroot +from zkb.enums import EnumCommand, EnumKernelBase, EnumPackageType, EnumChroot from zkb.managers import ResourceManager from zkb.commands import KernelCommand, AssetsCommand, BundleCommand @@ -46,6 +46,8 @@ def parse_args() -> argparse.Namespace: ) parser.add_argument( "--base", + type=EnumKernelBase, + choices=tuple(EnumKernelBase), help="select a kernel base for the build" ) parser.add_argument( From 77ebe9d4fb7ffc523c04add647c28b5a8f164bb1 Mon Sep 17 00:00:00 2001 From: Joseph Date: Mon, 2 Mar 2026 18:39:46 +0100 Subject: [PATCH 18/19] fix: adjust property definition --- zkb/commands/bundle.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/zkb/commands/bundle.py b/zkb/commands/bundle.py index 896fbec..2a09431 100644 --- a/zkb/commands/bundle.py +++ b/zkb/commands/bundle.py @@ -3,8 +3,7 @@ import shutil import logging import itertools -from pathlib import Path -from typing import Optional, Iterable +from typing import Optional from zkb.core import KernelBuilder, AssetsCollector from zkb.enums import EnumPackageType @@ -27,7 +26,7 @@ class BundleCommand(ModelConfig, ICommand): kernel_builder: KernelBuilder assets_collector: AssetsCollector - package_type: Iterable[EnumPackageType] + package_type: EnumPackageType base: str def build_kernel(self, clean_only: Optional[bool] = False) -> None: @@ -38,7 +37,7 @@ def build_kernel(self, clean_only: Optional[bool] = False) -> None: @property def __rom_only_flag(self) -> bool: - return True if EnumPackageType.FULL not in self.package_type else False + return True if self.package_type != EnumPackageType.FULL else False def collect_assets(self) -> None: self.assets_collector.clean_assets = True From 828184025bae1e921d0fd184f370dcbbe496cc0d Mon Sep 17 00:00:00 2001 From: Joseph Date: Mon, 2 Mar 2026 19:03:58 +0100 Subject: [PATCH 19/19] fix: convert property type --- zkb/engines/generic_container.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zkb/engines/generic_container.py b/zkb/engines/generic_container.py index f4dc9b1..512a6d7 100644 --- a/zkb/engines/generic_container.py +++ b/zkb/engines/generic_container.py @@ -30,7 +30,7 @@ class GenericContainerEngine(ModelConfig, IGenericContainerEngine): :param str base: Kernel source base. :param str lkv: Linux kernel version. :param typing.Optional[zkb.enums.EnumChroot]=None chroot: Chroot type. - :param typing.Optional[bool]=False package_type: Package type. + :param typing.Optional[zkb.enums.EnumPackageType]=False package_type: Package type. :param typing.Optional[bool]=False clean_kernel: Flag to clean folder for kernel storage. :param typing.Optional[bool]=False clean_assets: Flag to clean folder for assets storage. :param typing.Optional[bool]=False clean_image: Flag to clean a Docker/Podman image from local cache. @@ -51,7 +51,7 @@ class GenericContainerEngine(ModelConfig, IGenericContainerEngine): base: str lkv: Optional[str] = None chroot: Optional[EnumChroot] = None - package_type: Optional[str] = None + package_type: Optional[EnumPackageType] = None clean_kernel: Optional[bool] = False clean_assets: Optional[bool] = False clean_image: Optional[bool] = False