Coverage for src/data_api/models/buses.py: 100%

35 statements  

« prev     ^ index     » next       coverage.py v7.16.2, created at 2026-11-13 19:28 +0000

1""" 

2Shared bus response models. 

3 

4Pydantic models for request/response validation. 

5Enums are imported from domain layer to avoid duplication. 

6""" 

7 

8from pydantic import BaseModel, Field, field_validator 

9 

10from data_api.domain.buses.enums import ( 

11 BusDay, 

12 BusDayWithCurrent, 

13 BusDirection, 

14 BusRouteType, 

15 BusStopsName, 

16 BusType, 

17) 

18 

19__all__ = [ 

20 "BusStopsName", 

21 "BusRouteType", 

22 "BusType", 

23 "BusDirection", 

24 "BusDay", 

25 "BusDayWithCurrent", 

26 "BusInfo", 

27 "BusStopsInfo", 

28 "BusSchedule", 

29 "BusArriveTime", 

30 "BusDetailedSchedule", 

31 "BusCanonicalSchedule", 

32 "BusCanonicalDetailedSchedule", 

33] 

34 

35 

36class BusInfo(BaseModel): 

37 """Bus route information.""" 

38 

39 direction: str = Field(..., description="方向") 

40 duration: str = Field(..., description="時刻表有效期間") 

41 route: str = Field(..., description="路線") 

42 routeEN: str = Field(..., description="英文路線") 

43 

44 

45class BusStopsInfo(BaseModel): 

46 """Bus stop information.""" 

47 

48 name: str = Field(..., description="站牌中文名稱") 

49 name_en: str = Field(..., description="站牌英文名稱") 

50 latitude: str = Field(..., description="站牌所在地緯度") 

51 longitude: str = Field(..., description="站牌所在地經度") 

52 

53 

54class BusSchedule(BaseModel): 

55 """Unified bus schedule entry for both Main and Nanda campus.""" 

56 

57 time: str = Field(..., description="發車時間") 

58 description: str = Field(..., description="備註") 

59 dep_stop: str = Field(..., description="發車地點") 

60 line: str = Field("", description="路線 (主校區: red/green, 南大: route_1/route_2)") 

61 bus_type: BusType = Field(..., description="營運車輛類型") 

62 

63 

64class BusArriveTime(BaseModel): 

65 """Bus arrival time at a stop.""" 

66 

67 stop: str = Field(..., description="公車站牌名稱") 

68 arrive_time: str = Field(..., description="預計到達時間") 

69 

70 

71class BusDetailedSchedule(BaseModel): 

72 """Unified detailed bus schedule for both Main and Nanda campus.""" 

73 

74 dep_info: BusSchedule = Field(..., description="發車資訊") 

75 stops_time: list[BusArriveTime] = Field(..., description="各站發車時間") 

76 

77 

78class BusCanonicalSchedule(BusSchedule): 

79 """Schedule with campus-qualified line identifiers for the current API.""" 

80 

81 line: str = Field("", description="路線 (main_red/main_green/nanda_route_1/nanda_route_2)") 

82 arrive_time: str | None = Field( 

83 None, description="指定站牌的預計到達時間(僅在提供 stop 參數時回傳,未指定時省略)" 

84 ) 

85 

86 @field_validator("line") 

87 @classmethod 

88 def qualify_line(cls, line: str) -> str: 

89 return { 

90 "red": "main_red", 

91 "green": "main_green", 

92 "route_1": "nanda_route_1", 

93 "route_2": "nanda_route_2", 

94 }.get(line, line) 

95 

96 

97class BusCanonicalDetailedSchedule(BusDetailedSchedule): 

98 """Detailed schedule with campus-qualified departure line identifiers.""" 

99 

100 dep_info: BusCanonicalSchedule = Field(..., description="發車資訊") 

101 arrive_time: str | None = Field( 

102 None, description="指定站牌的預計到達時間(僅在提供 stop 參數時回傳,未指定時省略)" 

103 )