From 94a0f462bf64891bb446819f60c19405a4180352 Mon Sep 17 00:00:00 2001 From: Mark Paronyan Date: Mon, 28 Sep 2026 04:49:52 +0000 Subject: [PATCH 1/6] fix(typing): resolve mypy errors in schemas.controller.templates.iou_templates --- .../schemas/controller/templates/iou_templates.py | 12 ++++++++---- pyproject.toml | 1 - 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/gns3server/schemas/controller/templates/iou_templates.py b/gns3server/schemas/controller/templates/iou_templates.py index 02ab06696..36468d8aa 100644 --- a/gns3server/schemas/controller/templates/iou_templates.py +++ b/gns3server/schemas/controller/templates/iou_templates.py @@ -22,11 +22,11 @@ from pydantic import Field from typing import Optional -class IOUTemplate(TemplateBase): +class IOUTemplateBase(TemplateBase): category: Optional[Category] = Category.router default_name_format: Optional[str] = "IOU{0}" symbol: Optional[str] = "multilayer_switch" - path: str = Field(..., description="Path of IOU executable") + path: Optional[str] = Field(None, description="Path of IOU executable") ethernet_adapters: Optional[int] = Field(2, ge=0, description="Number of ethernet adapters") serial_adapters: Optional[int] = Field(2, ge=0, description="Number of serial adapters") ram: Optional[int] = Field(1024, gt=0, description="Amount of RAM in MB") @@ -44,5 +44,9 @@ class IOUTemplate(TemplateBase): ) -class IOUTemplateUpdate(IOUTemplate): - path: Optional[str] = Field(None, description="Path of IOU executable") +class IOUTemplate(IOUTemplateBase): + path: str = Field(..., description="Path of IOU executable") + + +class IOUTemplateUpdate(IOUTemplateBase): + pass diff --git a/pyproject.toml b/pyproject.toml index 258447eb6..23a3afc29 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -391,7 +391,6 @@ module = [ "gns3server.schemas.controller.projects", # 2 "gns3server.schemas.controller.settings", # 3 "gns3server.schemas.controller.templates.docker_templates", # 1 - "gns3server.schemas.controller.templates.iou_templates", # 1 "gns3server.schemas.controller.templates.virtualbox_templates", # 1 "gns3server.schemas.controller.templates.vmware_templates", # 1 "gns3server.schemas.qemu_disk_image", # 2 From edaf9a437721f083eabd9daf8865503f530efae2 Mon Sep 17 00:00:00 2001 From: Mark Paronyan Date: Mon, 28 Sep 2026 04:49:54 +0000 Subject: [PATCH 2/6] fix(typing): resolve mypy errors in schemas.controller.templates.virtualbox_templates --- .../controller/templates/virtualbox_templates.py | 12 ++++++++---- pyproject.toml | 1 - 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/gns3server/schemas/controller/templates/virtualbox_templates.py b/gns3server/schemas/controller/templates/virtualbox_templates.py index 3cce1cd6e..b9d966ec1 100644 --- a/gns3server/schemas/controller/templates/virtualbox_templates.py +++ b/gns3server/schemas/controller/templates/virtualbox_templates.py @@ -26,11 +26,11 @@ from pydantic import Field from typing import Optional, List -class VirtualBoxTemplate(TemplateBase): +class VirtualBoxTemplateBase(TemplateBase): category: Optional[Category] = Category.guest default_name_format: Optional[str] = "{name}-{0}" symbol: Optional[str] = "vbox_guest" - vmname: str = Field(..., description="VirtualBox VM name (in VirtualBox itself)") + vmname: Optional[str] = Field(None, description="VirtualBox VM name (in VirtualBox itself)") ram: Optional[int] = Field(256, gt=0, description="Amount of RAM in MB") linked_clone: Optional[bool] = Field(False, description="Whether the VM is a linked clone or not") adapters: Optional[int] = Field( @@ -59,5 +59,9 @@ class VirtualBoxTemplate(TemplateBase): custom_adapters: Optional[List[CustomAdapter]] = Field(default_factory=list, description="Custom adapters") -class VirtualBoxTemplateUpdate(VirtualBoxTemplate): - vmname: Optional[str] = Field(None, description="VirtualBox VM name (in VirtualBox itself)") +class VirtualBoxTemplate(VirtualBoxTemplateBase): + vmname: str = Field(..., description="VirtualBox VM name (in VirtualBox itself)") + + +class VirtualBoxTemplateUpdate(VirtualBoxTemplateBase): + pass diff --git a/pyproject.toml b/pyproject.toml index 23a3afc29..f5189aab4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -391,7 +391,6 @@ module = [ "gns3server.schemas.controller.projects", # 2 "gns3server.schemas.controller.settings", # 3 "gns3server.schemas.controller.templates.docker_templates", # 1 - "gns3server.schemas.controller.templates.virtualbox_templates", # 1 "gns3server.schemas.controller.templates.vmware_templates", # 1 "gns3server.schemas.qemu_disk_image", # 2 "gns3server.services.computes", # 4 From 79862d900a5c536757bbd54f58be25c3a8dc1721 Mon Sep 17 00:00:00 2001 From: Mark Paronyan Date: Mon, 28 Sep 2026 04:49:56 +0000 Subject: [PATCH 3/6] fix(typing): resolve mypy errors in schemas.controller.templates.vmware_templates --- .../schemas/controller/templates/vmware_templates.py | 12 ++++++++---- pyproject.toml | 1 - 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/gns3server/schemas/controller/templates/vmware_templates.py b/gns3server/schemas/controller/templates/vmware_templates.py index 4aed1ee90..85d9dce96 100644 --- a/gns3server/schemas/controller/templates/vmware_templates.py +++ b/gns3server/schemas/controller/templates/vmware_templates.py @@ -27,11 +27,11 @@ from pydantic import Field from typing import Optional, List -class VMwareTemplate(TemplateBase): +class VMwareTemplateBase(TemplateBase): category: Optional[Category] = Category.guest default_name_format: Optional[str] = "{name}-{0}" symbol: Optional[str] = "vmware_guest" - vmx_path: str = Field(..., description="Path to the vmx file") + vmx_path: Optional[str] = Field(None, description="Path to the vmx file") linked_clone: Optional[bool] = Field(False, description="Whether the VM is a linked clone or not") first_port_name: Optional[str] = Field("", description="Optional name of the first networking port example: eth0") port_name_format: Optional[str] = Field( @@ -57,5 +57,9 @@ class VMwareTemplate(TemplateBase): custom_adapters: Optional[List[CustomAdapter]] = Field(default_factory=list, description="Custom adapters") -class VMwareTemplateUpdate(VMwareTemplate): - vmx_path: Optional[str] = Field(None, description="Path to the vmx file") +class VMwareTemplate(VMwareTemplateBase): + vmx_path: str = Field(..., description="Path to the vmx file") + + +class VMwareTemplateUpdate(VMwareTemplateBase): + pass diff --git a/pyproject.toml b/pyproject.toml index f5189aab4..984fe66fe 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -391,7 +391,6 @@ module = [ "gns3server.schemas.controller.projects", # 2 "gns3server.schemas.controller.settings", # 3 "gns3server.schemas.controller.templates.docker_templates", # 1 - "gns3server.schemas.controller.templates.vmware_templates", # 1 "gns3server.schemas.qemu_disk_image", # 2 "gns3server.services.computes", # 4 "gns3server.services.templates", # 18 From 9bad1d92f8a829ffed284953bd857cfba595d422 Mon Sep 17 00:00:00 2001 From: Mark Paronyan Date: Mon, 28 Sep 2026 04:54:50 +0000 Subject: [PATCH 4/6] fix(typing): resolve mypy errors in schemas.qemu_disk_image --- gns3server/schemas/qemu_disk_image.py | 9 ++++----- pyproject.toml | 1 - 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/gns3server/schemas/qemu_disk_image.py b/gns3server/schemas/qemu_disk_image.py index a3ebccba6..1c0f596ad 100644 --- a/gns3server/schemas/qemu_disk_image.py +++ b/gns3server/schemas/qemu_disk_image.py @@ -78,8 +78,8 @@ class QemuDiskImageAdapterType(str, Enum): class QemuDiskImageBase(BaseModel): - format: QemuDiskImageFormat = Field(..., description="Image format type") - size: int = Field(..., description="Image size in Megabytes") + format: Optional[QemuDiskImageFormat] = Field(None, description="Image format type") + size: Optional[int] = Field(None, description="Image size in Megabytes") preallocation: Optional[QemuDiskImagePreallocation] = None cluster_size: Optional[int] = None refcount_bits: Optional[int] = None @@ -91,10 +91,9 @@ class QemuDiskImageBase(BaseModel): class QemuDiskImageCreate(QemuDiskImageBase): - pass + format: QemuDiskImageFormat = Field(..., description="Image format type") + size: int = Field(..., description="Image size in Megabytes") class QemuDiskImageUpdate(QemuDiskImageBase): - format: Optional[QemuDiskImageFormat] = Field(None, description="Image format type") - size: Optional[int] = Field(None, description="Image size in Megabytes") extend: Optional[int] = Field(None, description="Number of Megabytes to extend the image") diff --git a/pyproject.toml b/pyproject.toml index 984fe66fe..a9780d39c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -391,7 +391,6 @@ module = [ "gns3server.schemas.controller.projects", # 2 "gns3server.schemas.controller.settings", # 3 "gns3server.schemas.controller.templates.docker_templates", # 1 - "gns3server.schemas.qemu_disk_image", # 2 "gns3server.services.computes", # 4 "gns3server.services.templates", # 18 "gns3server.utils.asyncio.aiozipstream", # 8 From e6053dd0a8b4c9c377bab0081b4091761c2c8823 Mon Sep 17 00:00:00 2001 From: Mark Paronyan Date: Mon, 28 Sep 2026 05:10:23 +0000 Subject: [PATCH 5/6] fix(typing): resolve mypy errors in services.computes --- gns3server/db/repositories/computes.py | 10 ++++++---- pyproject.toml | 1 - 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/gns3server/db/repositories/computes.py b/gns3server/db/repositories/computes.py index 4f3aac7f4..5747fbf03 100644 --- a/gns3server/db/repositories/computes.py +++ b/gns3server/db/repositories/computes.py @@ -16,7 +16,7 @@ # along with this program. If not, see . from uuid import UUID -from typing import Optional, List +from typing import Optional, List, Union from sqlalchemy import select, update, delete from sqlalchemy.ext.asyncio import AsyncSession @@ -31,7 +31,7 @@ class ComputesRepository(BaseRepository): super().__init__(db_session) - async def get_compute(self, compute_id: UUID) -> Optional[models.Compute]: + async def get_compute(self, compute_id: Union[str, UUID]) -> Optional[models.Compute]: query = select(models.Compute).where(models.Compute.compute_id == compute_id) result = await self._db_session.execute(query) @@ -65,7 +65,9 @@ class ComputesRepository(BaseRepository): await self._db_session.refresh(db_compute) return db_compute - async def update_compute(self, compute_id: UUID, compute_update: schemas.ComputeUpdate) -> Optional[models.Compute]: + async def update_compute( + self, compute_id: Union[str, UUID], compute_update: schemas.ComputeUpdate + ) -> Optional[models.Compute]: update_values = compute_update.model_dump(exclude_unset=True) if compute_update.password is not None: @@ -80,7 +82,7 @@ class ComputesRepository(BaseRepository): await self._db_session.refresh(compute_db) # force refresh of updated_at value return compute_db - async def delete_compute(self, compute_id: UUID) -> bool: + async def delete_compute(self, compute_id: Union[str, UUID]) -> bool: query = delete(models.Compute).where(models.Compute.compute_id == compute_id) result = await self._db_session.execute(query) diff --git a/pyproject.toml b/pyproject.toml index a9780d39c..1179d2526 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -391,7 +391,6 @@ module = [ "gns3server.schemas.controller.projects", # 2 "gns3server.schemas.controller.settings", # 3 "gns3server.schemas.controller.templates.docker_templates", # 1 - "gns3server.services.computes", # 4 "gns3server.services.templates", # 18 "gns3server.utils.asyncio.aiozipstream", # 8 "gns3server.utils.encryption", # 2 From df8b3c2903a6553506cd3dcc0c1afb11507d71da Mon Sep 17 00:00:00 2001 From: Mark Paronyan Date: Mon, 28 Sep 2026 06:14:38 +0000 Subject: [PATCH 6/6] fix(typing): resolve mypy errors in utils.asyncio.aiozipstream --- gns3server/utils/asyncio/aiozipstream.py | 18 ++++++++---------- pyproject.toml | 1 - 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/gns3server/utils/asyncio/aiozipstream.py b/gns3server/utils/asyncio/aiozipstream.py index a6e1fc49b..1efafc37e 100644 --- a/gns3server/utils/asyncio/aiozipstream.py +++ b/gns3server/utils/asyncio/aiozipstream.py @@ -32,16 +32,14 @@ import asyncio import aiofiles from concurrent import futures -from zipfile import ( - structCentralDir, - structEndArchive64, - structEndArchive, - structEndArchive64Locator, - stringCentralDir, - stringEndArchive64, - stringEndArchive, - stringEndArchive64Locator, -) +structCentralDir = "<4s4B4HL2L5H2L" +structEndArchive64 = "<4sQ2H2L4Q" +structEndArchive = b"<4s4H2LH" +structEndArchive64Locator = "<4sLQL" +stringCentralDir = b"PK\x01\x02" +stringEndArchive64 = b"PK\x06\x06" +stringEndArchive = b"PK\x05\x06" +stringEndArchive64Locator = b"PK\x06\x07" ZIP_ZSTANDARD = 93 # zstandard is supported by WinZIP v24 and later, PowerArchiver 2021 and 7-Zip-zstd diff --git a/pyproject.toml b/pyproject.toml index 1179d2526..63bfde2eb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -392,7 +392,6 @@ module = [ "gns3server.schemas.controller.settings", # 3 "gns3server.schemas.controller.templates.docker_templates", # 1 "gns3server.services.templates", # 18 - "gns3server.utils.asyncio.aiozipstream", # 8 "gns3server.utils.encryption", # 2 "gns3server.utils.http_client", # 4 "gns3server.utils.images", # 4