From 9323ea4cec15fc5433af39aaa5ddf8952e5457ef Mon Sep 17 00:00:00 2001 From: YueGuobin Date: Mon, 3 Aug 2026 00:31:45 +0800 Subject: [PATCH] schema: accept direction='both' in marker schemas, normalize to None --- gns3server/schemas/controller/links.py | 29 +++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/gns3server/schemas/controller/links.py b/gns3server/schemas/controller/links.py index 31bdc607a..dd4b4ce5c 100644 --- a/gns3server/schemas/controller/links.py +++ b/gns3server/schemas/controller/links.py @@ -14,7 +14,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -from pydantic import BaseModel, Field +from pydantic import BaseModel, Field, field_validator from typing import List, Optional, Tuple from enum import Enum from uuid import UUID, uuid4 @@ -177,8 +177,8 @@ class MarkerCreate(BaseModel): ) direction: Optional[str] = Field( None, - pattern=r"^(tx|rx)$", - description="Direction filter: 'tx' = capture node sending only, 'rx' = capture node receiving only. Omitted or null = both directions.", + pattern=r"^(tx|rx|both)$", + description="Direction filter: 'tx' = capture node sending only, 'rx' = capture node receiving only, 'both' or null = both directions.", ) capture_node_id: Optional[UUID] = Field( None, @@ -190,6 +190,11 @@ class MarkerCreate(BaseModel): ), ) + @field_validator("direction", mode="before") + @classmethod + def _both_to_none(cls, v): + return None if v == "both" else v + class MarkerUpdate(BaseModel): """ @@ -204,8 +209,8 @@ class MarkerUpdate(BaseModel): tag: Optional[int] = None direction: Optional[str] = Field( None, - pattern=r"^(tx|rx)$", - description="Direction filter; an explicit null clears it to both. Omit to keep.", + pattern=r"^(tx|rx|both)$", + description="Direction filter; 'both' or an explicit null clears it to both. Omit to keep.", ) color: Optional[str] = Field(None, description="Hex color render hint, e.g. '#ff5722'") highlight_duration: Optional[int] = Field( @@ -213,6 +218,11 @@ class MarkerUpdate(BaseModel): ) enabled: Optional[bool] = Field(None, description="Toggle the marker on/off (instant).") + @field_validator("direction", mode="before") + @classmethod + def _both_to_none(cls, v): + return None if v == "both" else v + class MarkerDefinitionCreate(BaseModel): """ @@ -246,8 +256,13 @@ class MarkerDefinitionCreate(BaseModel): ) direction: Optional[str] = Field( None, - pattern=r"^(tx|rx)$", - description="Direction filter: 'tx' = capture node sending only, 'rx' = capture node receiving only. Omitted or null = both directions.", + pattern=r"^(tx|rx|both)$", + description="Direction filter: 'tx' = capture node sending only, 'rx' = capture node receiving only, 'both' or null = both directions.", ) + @field_validator("direction", mode="before") + @classmethod + def _both_to_none(cls, v): + return None if v == "both" else v +