Define dataclasses to represent API json 🟩

This commit is contained in:
Daniel Roth 2026-05-05 10:28:07 +00:00
parent 0ba0beed3f
commit 18a58486af
5 changed files with 280 additions and 1 deletions

View file

View file

View file

@ -0,0 +1,279 @@
from typing import Any, Optional, Union
from pydantic import BaseModel, ConfigDict, Field
_IGNORE = ConfigDict(extra="ignore")
_IGNORE_POPULATE = ConfigDict(extra="ignore", populate_by_name=True)
class Vec3(BaseModel):
model_config = _IGNORE
x: float
y: float
z: float
class Symbol(BaseModel):
model_config = _IGNORE
id: str
name: str
description: Optional[str] = None
valid: bool
class FieldValue(BaseModel):
model_config = _IGNORE
index: int
has_value: bool
is_array: bool
value: Union[str, list[str]]
class SurveyField(BaseModel):
model_config = _IGNORE
id: str
type: int
type_as_string: str
is_required: bool
label: str
description: Optional[str] = None
list_values: list[str] = []
value: FieldValue
class ImageMapEntry(BaseModel):
model_config = _IGNORE
symbol_id: str
uid: str
owner_uid: str
type: int
coordinates: list[int]
class FormattedDimensions(BaseModel):
model_config = _IGNORE
width: Optional[str] = None
depth: Optional[str] = None
height: Optional[str] = None
class FormattedMeasures(BaseModel):
model_config = _IGNORE
width: Optional[str] = None
depth: Optional[str] = None
height: Optional[str] = None
area: Optional[str] = None
area_without_walls: Optional[str] = None
area_with_interior_walls_only: Optional[str] = None
area_with_walls: Optional[str] = None
doors_surface: Optional[str] = None
walls_surface: Optional[str] = None
walls_surface_without_openings: Optional[str] = None
windows_surface: Optional[str] = None
perimeter: Optional[str] = None
ground_perimeter: Optional[str] = None
living_area: Optional[str] = None
below_grade_living_area: Optional[str] = None
above_grade_living_area: Optional[str] = None
exterior_perimeter: Optional[str] = None
volume: Optional[str] = None
class Address(BaseModel):
model_config = _IGNORE
street: Optional[str] = None
street_number: Optional[str] = None
postal_code: Optional[str] = None
city: Optional[str] = None
country: Optional[str] = None
longitude: Optional[float] = None
latitude: Optional[float] = None
class CreatedBy(BaseModel):
model_config = _IGNORE
id: str
email: str
firstname: Optional[str] = None
lastname: Optional[str] = None
class Location(BaseModel):
model_config = _IGNORE
valid: bool
longitude: float
latitude: float
altitude: float
class ItemBase(BaseModel):
model_config = _IGNORE
uid: str
symbol: Symbol
size: Vec3
position: Vec3
rotation: Vec3
formatted: Optional[FormattedDimensions] = None
images: list[Any] = []
notes: Optional[str] = None
displayable_fields: list[SurveyField] = []
custom_displayable_fields: list[SurveyField] = []
class WallItem(ItemBase):
pass
class Furniture(ItemBase):
pass
class SymbolInstance(ItemBase):
pass
class Wall(BaseModel):
model_config = _IGNORE
uid: str
symbol: Symbol
length: float
images: list[Any] = []
notes: Optional[str] = None
displayable_fields: list[SurveyField] = []
custom_displayable_fields: list[SurveyField] = []
class Room(BaseModel):
model_config = _IGNORE
name: str
uid: str
symbol: Optional[Symbol] = None
size: Vec3
position: Vec3
rotation: Vec3
area: float
perimeter: Optional[float] = None
ground_perimeter: Optional[float] = None
area_without_walls: Optional[float] = None
area_with_interior_walls_only: Optional[float] = None
area_with_walls: Optional[float] = None
wall_count: Optional[int] = None
wall_count_with_interior_walls: Optional[int] = None
corner_count_with_interior_walls: Optional[int] = None
door_count: Optional[int] = None
window_count: Optional[int] = None
height: Optional[float] = None
volume: Optional[float] = None
width: Optional[float] = None
doors_surface: Optional[float] = None
walls_surface: Optional[float] = None
walls_surface_without_openings: Optional[float] = None
windows_surface: Optional[float] = None
room_type: Optional[str] = None
furniture_count: Optional[int] = None
image: Optional[str] = None
image_map: list[ImageMapEntry] = []
images: list[Any] = []
notes: Optional[str] = None
formatted: Optional[FormattedMeasures] = None
displayable_fields: list[SurveyField] = []
custom_displayable_fields: list[SurveyField] = []
wall_items: list[WallItem] = []
furnitures: list[Furniture] = []
walls: list[Wall] = []
class Floor(BaseModel):
model_config = _IGNORE
uid: str
symbol: Optional[Symbol] = None
size: Vec3
position: Vec3
rotation: Vec3
name: Optional[str] = None
area: Optional[float] = None
perimeter: Optional[float] = None
ground_perimeter: Optional[float] = None
area_without_walls: Optional[float] = None
area_with_interior_walls_only: Optional[float] = None
area_with_walls: Optional[float] = None
wall_count: Optional[int] = None
wall_count_with_interior_walls: Optional[int] = None
corner_count_with_interior_walls: Optional[int] = None
door_count: Optional[int] = None
window_count: Optional[int] = None
bathrooms_count: Optional[int] = None
bedrooms_count: Optional[int] = None
doors_surface: Optional[float] = None
floor_type: Optional[Union[int, str]] = None
furniture_count: Optional[int] = None
height: Optional[float] = None
level: Optional[int] = None
room_count: Optional[int] = None
volume: Optional[float] = None
walls_surface: Optional[float] = None
walls_surface_without_openings: Optional[float] = None
windows_surface: Optional[float] = None
image: Optional[str] = None
image_map: list[ImageMapEntry] = []
images: list[Any] = []
notes: Optional[str] = None
formatted: Optional[FormattedMeasures] = None
displayable_fields: list[SurveyField] = []
custom_displayable_fields: list[SurveyField] = []
rooms: list[Room] = []
furnitures: list[Furniture] = []
symbol_instances: list[SymbolInstance] = []
class PlanBody(BaseModel):
model_config = _IGNORE
uid: str
name: Optional[str] = None
symbol: Optional[Symbol] = None
size: Vec3
position: Vec3
rotation: Vec3
area: Optional[float] = None
location: Location
floors: list[Floor] = []
images: list[Any] = []
notes: Optional[str] = None
formatted: Optional[FormattedMeasures] = None
displayable_fields: list[SurveyField] = []
custom_displayable_fields: list[SurveyField] = []
customer: list[Any] = []
custom_attributes: list[Any] = []
class PlanDetail(BaseModel):
model_config = _IGNORE
extension_version: Optional[str] = None
wrapper_version: Optional[str] = None
document_version: Optional[str] = None
last_modification_date: Optional[Union[int, str]] = None
plan: PlanBody
class PlanSummary(BaseModel):
model_config = _IGNORE_POPULATE
id: str
project_id: Optional[str] = None
name: str
address: Optional[Address] = None
creation_date: Optional[str] = None
update_date: Optional[str] = None
thumbnail_url: Optional[str] = None
public_url: Optional[str] = None
cloud_url: Optional[str] = None
url_3d: Optional[str] = Field(default=None, alias="3d_url")
workgroup_id: Optional[str] = None
team_id: Optional[str] = None
created_by: Optional[CreatedBy] = None
class MagicPlan(BaseModel):
model_config = _IGNORE
plan: PlanSummary
plan_detail: PlanDetail

View file

@ -3,6 +3,6 @@ pythonpath = .
log_cli = true
log_cli_level = INFO
addopts = --cov-report term-missing --cov=etl/epc --cov=recommendations --cov=backend --cov=etl/epc_clean --cov=etl/spatial
testpaths = recommendations/tests backend/tests etl/epc/tests etl/epc_clean/tests etl/spatial/tests backend/condition/tests backend/address2UPRN/tests backend/onboarders/tests backend/categorisation/tests backend/export/tests etl/hubspot/tests backend/hubspot_trigger_orchestrator/tests datatypes/epc/schema/tests datatypes/epc/surveys/tests datatypes/epc/domain/tests backend/ecmk_fetcher/tests/ backend/pashub_fetcher/tests backend/documents_parser/tests backend/magic_plan/tests
testpaths = recommendations/tests backend/tests etl/epc/tests etl/epc_clean/tests etl/spatial/tests backend/condition/tests backend/address2UPRN/tests backend/onboarders/tests backend/categorisation/tests backend/export/tests etl/hubspot/tests backend/hubspot_trigger_orchestrator/tests datatypes/epc/schema/tests datatypes/epc/surveys/tests datatypes/epc/domain/tests backend/ecmk_fetcher/tests/ backend/pashub_fetcher/tests backend/documents_parser/tests backend/magic_plan/tests datatypes/magicplan/api/tests
markers =
integration: mark a test as an integration test