Skip to content
Snippets Groups Projects
Commit 863f0a66 authored by Mohammad Torkashvand's avatar Mohammad Torkashvand
Browse files

make lat and long string

refactor site validation
parent 7d2fb24d
No related branches found
No related tags found
1 merge request!214make lat and long string
Pipeline #86757 failed
......@@ -20,7 +20,6 @@ from gso.db.models import PartnerTable
from gso.products import ProductType
from gso.products.product_blocks.iptrunk import IptrunkType, PhysicalPortCapacity
from gso.products.product_blocks.router import RouterRole
from gso.products.product_blocks.site import SiteTier
from gso.services.partners import PartnerNotFoundError, get_partner_by_name
from gso.services.subscriptions import (
get_active_router_subscriptions,
......@@ -36,18 +35,6 @@ app: typer.Typer = typer.Typer()
class SiteImportModel(BaseSiteValidatorModel):
"""The required input for importing an existing :class:`gso.products.product_types.site`."""
site_name: str
site_city: str
site_country: str
site_country_code: str
site_latitude: float
site_longitude: float
site_bgp_community_id: int
site_internal_id: int
site_tier: SiteTier
site_ts_address: str
partner: str
class RouterImportModel(BaseModel):
"""Required fields for importing an existing :class:`gso.product.product_types.router`."""
......
......@@ -5,9 +5,15 @@ from typing import Annotated
from orchestrator.domain.base import ProductBlockModel
from orchestrator.types import SubscriptionLifecycle, strEnum
from pydantic import AfterValidator, Field
from pydantic import AfterValidator
from typing_extensions import Doc
MAX_LONGITUDE = 180
MIN_LONGITUDE = -180
MAX_LATITUDE = 90
MIN_LATITUDE = -90
class SiteTier(strEnum):
"""The tier of a site, ranging from 1 to 4.
......@@ -22,31 +28,36 @@ class SiteTier(strEnum):
TIER4 = 4
def validate_latitude(v: float) -> float:
def validate_latitude(v: str) -> str:
"""Validate a latitude coordinate."""
msg = "Invalid latitude coordinate. Valid examples: '40.7128', '-74.0060', '90', '-90', '0'."
regex = re.compile(r"^-?([1-8]?\d(\.\d+)?|90(\.0+)?)$")
if not regex.match(str(v)):
msg = "Invalid latitude coordinate. Valid examples: '40.7128', '-74.0060', '90', '-90', '0'."
raise ValueError(msg)
float_v = float(v)
if float_v > MAX_LATITUDE or float_v < MIN_LATITUDE:
raise ValueError(msg)
return v
def validate_longitude(v: float) -> float:
def validate_longitude(v: str) -> str:
"""Validate a longitude coordinate."""
regex = re.compile(r"^-?(180(\.0+)?|((1[0-7]\d)|([1-9]?\d))(\.\d+)?)$")
if not regex.match(str(v)):
msg = "Invalid longitude coordinate. Valid examples: '40.7128', '-74.0060', '180', '-180', '0'."
msg = "Invalid longitude coordinate. Valid examples: '40.7128', '-74.0060', '180', '-180', '0'."
if not regex.match(v):
raise ValueError(msg)
float_v = float(v)
if float_v > MAX_LONGITUDE or float_v < MIN_LONGITUDE:
raise ValueError(msg)
return v
LatitudeCoordinate = Annotated[
float,
Field(
ge=-90,
le=90,
),
str,
AfterValidator(validate_latitude),
Doc(
"A latitude coordinate, modeled as a string. "
......@@ -56,11 +67,7 @@ LatitudeCoordinate = Annotated[
]
LongitudeCoordinate = Annotated[
float,
Field(
ge=-180,
le=180,
),
str,
AfterValidator(validate_longitude),
Doc(
"A longitude coordinate, modeled as a string. "
......
......@@ -213,6 +213,7 @@ class BaseSiteValidatorModel(BaseModel):
site_country: str
site_latitude: LatitudeCoordinate
site_longitude: LongitudeCoordinate
partner: str
@field_validator("site_ts_address")
def validate_ts_address(cls, site_ts_address: str) -> str:
......
......@@ -14,6 +14,7 @@ from gso.products.product_blocks.site import LatitudeCoordinate, LongitudeCoordi
from gso.products.product_types.site import ImportedSiteInactive
from gso.services import subscriptions
from gso.services.partners import get_partner_by_name
from gso.utils.helpers import BaseSiteValidatorModel
@step("Create subscription")
......@@ -32,21 +33,9 @@ def create_subscription(partner: str) -> State:
def generate_initial_input_form() -> FormGenerator:
"""Generate a form that is filled in using information passed through the :term:`API` endpoint."""
class ImportSite(FormPage):
class ImportSite(FormPage, BaseSiteValidatorModel):
model_config = ConfigDict(title="Import Site")
site_name: str
site_city: str
site_country: str
site_country_code: str
site_latitude: float
site_longitude: float
site_bgp_community_id: int
site_internal_id: int
site_tier: SiteTier
site_ts_address: str
partner: str
user_input = yield ImportSite
return user_input.dict()
......
......@@ -103,8 +103,8 @@ def site_data(faker, temp_file):
"site_city": faker.city(),
"site_country": faker.country(),
"site_country_code": faker.country_code(),
"site_latitude": float(faker.latitude()),
"site_longitude": float(faker.longitude()),
"site_latitude": str(faker.latitude()),
"site_longitude": str(faker.longitude()),
"site_bgp_community_id": faker.pyint(),
"site_internal_id": faker.pyint(),
"site_tier": SiteTier.TIER1,
......@@ -228,12 +228,12 @@ def test_import_site_with_invalid_data(mock_start_process, site_data, capfd):
assert "Validation error: 2 validation errors for SiteImportModel" in captured_output
assert (
"""site_latitude
Input should be a valid number [type=float_type, input_value=None, input_type=NoneType]"""
Input should be a valid string [type=string_type, input_value=None, input_type=NoneType]"""
in captured_output
)
assert (
"""site_longitude
Input should be a valid number, unable to parse string as a number [type=float_parsing, input_value='broken',"""
Value error, Invalid longitude coordinate. Valid examples: '40.7128', '-74.0060', '180', '-180', '0'. [type=value_error, input_value='broken', input_type=str]"""
in captured_output
)
......
......@@ -59,8 +59,8 @@ def site_subscription_factory(faker, geant_partner):
site_city = site_city or faker.city()
site_country = site_country or faker.country()
site_country_code = site_country_code or faker.country_code()
site_latitude = site_latitude or float(faker.latitude())
site_longitude = site_longitude or float(faker.longitude())
site_latitude = site_latitude or str(faker.latitude())
site_longitude = site_longitude or str(faker.longitude())
site_bgp_community_id = site_bgp_community_id or faker.pyint()
site_internal_id = site_internal_id or faker.pyint()
site_ts_address = site_ts_address or faker.ipv4()
......
......@@ -15,18 +15,18 @@ class LongitudeModel(BaseModel):
@pytest.mark.parametrize(
("input_value", "is_valid"),
[
(40.7128, True),
(-74.0060, True),
(90, True),
(-90, True),
(0, True),
(45.6, True),
(91, False),
(-91, False),
(180, False),
(-180, False),
("40.7128", True),
("-74.0060", True),
("90", True),
("-90", True),
("0", True),
("45.6", True),
("91", False),
("-91", False),
("180", False),
("-180", False),
("abc", False),
(90.1, False),
("90.1", False),
],
)
def test_latitude(input_value, is_valid):
......@@ -40,16 +40,16 @@ def test_latitude(input_value, is_valid):
@pytest.mark.parametrize(
("input_value", "is_valid"),
[
(40.7128, True),
(-74.0060, True),
(180, True),
(-180, True),
(0, True),
(90.1, True),
(181, False),
(-181, False),
(200, False),
(-200, False),
("40.7128", True),
("-74.0060", True),
("180", True),
("-180", True),
("0", True),
("90.1", True),
("181", False),
("-181", False),
("200", False),
("-200", False),
("abc", False),
("90a", False),
],
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment