콘텐츠로 이동

srt_mobile_api.models

요청 입력과 응답 결과의 값 타입 전부.

SRT 앱은 WebView 껍데기라 서버가 돌려주는 것이 대개 렌더링된 HTML 입니다. srt_mobile_api.parsers 가 그 HTML 에서 뽑아낸 값이 여기 있는 frozen dataclass 로 들어옵니다. 원본 페이지가 필요할 때를 위해 HtmlPage 계열이 따로 있습니다.

여기 있는 것은 값 객체일 뿐이라 아무것도 전송하지 않습니다. 상태를 바꾸려면 MutationConsent 로 범주를 열어야 합니다.

민감한 필드 — 카드번호, 카드 비밀번호, 생년월일, PNR, 쿠폰번호, NetFunnel 키 — 는 repr 에서 빠지므로 객체를 그대로 찍어도 값이 새지 않습니다.

전선에 실릴 값은 만들 때 검사합니다. 역코드·날짜·시각 같은 자리는 ASCII 숫자열이어야 하고(_is_digits), 코드값 셋(SrtTrainGroupCode, SrtSeatAttrCode)은 Literal 별칭이면서 런타임에서도 다시 좁혀집니다.

SrtTrainGroupCode module-attribute

SrtTrainGroupCode = Literal['300', '900', '109']

SrtSeatAttrCode module-attribute

SrtSeatAttrCode = Literal['015', '021', '028']

INSTALLMENT_MONTH_OPTIONS module-attribute

INSTALLMENT_MONTH_OPTIONS = frozenset({0, *(range(2, 13)), 24})

SeatType

Bases: Enum

예약할 좌석 등급 선호. srtgo 의 같은 열거형을 옮긴 것입니다(srt.py:413-417).

*_FIRST 는 한쪽을 먼저 보되 그 열차의 잔여석에 따라 다른 쪽으로 넘어가고, *_ONLY 는 잔여석과 무관하게 한 등급만 고집합니다.

GENERAL_FIRST class-attribute instance-attribute

GENERAL_FIRST = 1

GENERAL_ONLY class-attribute instance-attribute

GENERAL_ONLY = 2

SPECIAL_FIRST class-attribute instance-attribute

SPECIAL_FIRST = 3

SPECIAL_ONLY class-attribute instance-attribute

SPECIAL_ONLY = 4

SrtSession dataclass

SrtSession(login_id=None, user_map=dict())

login_id class-attribute instance-attribute

login_id = field(default=None, repr=False)

user_map class-attribute instance-attribute

user_map = field(default_factory=dict, repr=False)

membership_number property

membership_number

계정의 회원번호 — 로그인 응답 userMapMB_CRD_NO 를 꺼내 줍니다.

카드결제 폼이 mbCrdNo 로 이 값을 싣기 때문에 필요합니다.

키가 없거나 문자열이 아니면 "" 입니다. 빈 값이 곧 "로그인하지 않음"이라는 것은 앱 자신의 관례입니다 (docs/analysis/full-api-analysis-2026-07-20.md:431).

근거의 출처가 반씩 다릅니다. mbCrdNo 라는 이름은 앱의 것이고 (ara0101v.js:319,321), 그것이 Ata09036 결제 본문에 실린다는 것은 참조 구현들의 실제 전송에만 근거가 있습니다 (card_payment_payload 참고).

PassengerCounts dataclass

PassengerCounts(adult=1, child=0, senior=0, disability_1_to_3=0, disability_4_to_6=0, infant=0, youth=0)

승차인원 — 앱의 일곱 가지 승객 유형. 그중 다섯만 자기 슬롯으로 나갑니다.

유아는 자기 psgTpCd 가 없어 어린이 슬롯에 접힙니다. 예약 페이지의 goRevFn 이 어린이 슬롯에 유아를 더하고 infantCnt 로 따로 선언합니다. 접힌 수는 child_slot_count 이고, child 와 구분됩니다.

청소년은 슬롯이 있습니다 — psgTpCd 6. commCode.js 어느 사본에도 없지만 공공할인 04 경로의 승차인원선택 popup에서 나타납니다.

Live-verified 2026-07-26: child=2,infant=3 → psgTpCd2="5", psgInfoPerPrnb2="5", infantCnt="3"; youth=1 → psgTpCd2="6". 청소년으로 실제 예약이 되는지는 미확인.

adult class-attribute instance-attribute

adult = 1

child class-attribute instance-attribute

child = 0

senior class-attribute instance-attribute

senior = 0

disability_1_to_3 class-attribute instance-attribute

disability_1_to_3 = 0

disability_4_to_6 class-attribute instance-attribute

disability_4_to_6 = 0

infant class-attribute instance-attribute

infant = 0

youth class-attribute instance-attribute

youth = 0

child_slot_count property

child_slot_count

어린이 슬롯(psgTpCd 5)에 실리는 수 — 어린이 + 유아.

편의를 위한 합이 아니라 앱이 실제로 하는 접기입니다. 예약 페이지(goRevFn)도 할인 승차권 페이지(setPassenger_callbackparseInt(obj.passenger5) + parseInt(obj.passenger6))도 똑같이 더합니다.

어린이 없이 유아만 있어도 이 슬롯은 채워집니다. 앱의 검사가 합에 걸려 있으므로(if(passenger != '0')) PassengerCounts(adult=1, infant=1) 은 어린이 슬롯 1 과 infantCnt=1 을 함께 보냅니다. 페이지가 하는 그대로이고, 여기서 다듬지 않습니다.

total property

total

총 인원(totPrnb) — 유아까지 포함한 머릿수.

유아가 세어지는 것은 앱의 totPrnb += passenger 가 접기 뒤에 실행되기 때문입니다. 팝업의 setTotalPassengeri=1..7 을 전부 더합니다.

따라서 getPsgTotCnt()(ara0101v.js:35)가 보장하는 등식은 실제로 나가는 슬롯들에 대해 totPrnb == sum(psgInfoPerPrnb…) 이고, 이 속성이 그 값입니다.

NetFunnelToken dataclass

NetFunnelToken(action, key, raw_type, code, params=dict())

action instance-attribute

action

key class-attribute instance-attribute

key = field(repr=False)

raw_type instance-attribute

raw_type

code instance-attribute

code

params class-attribute instance-attribute

params = field(default_factory=dict, repr=False)

TrainSearchQuery dataclass

TrainSearchQuery(departure_station_code, arrival_station_code, departure_date, departure_time='060000', passengers=PassengerCounts(), train_group_code='109', seat_attr_code='015', departure_station_name=None, arrival_station_name=None)

departure_station_code instance-attribute

departure_station_code

arrival_station_code instance-attribute

arrival_station_code

departure_date instance-attribute

departure_date

departure_time class-attribute instance-attribute

departure_time = '060000'

passengers class-attribute instance-attribute

passengers = field(default_factory=PassengerCounts)

train_group_code class-attribute instance-attribute

train_group_code = '109'

seat_attr_code class-attribute instance-attribute

seat_attr_code = '015'

departure_station_name class-attribute instance-attribute

departure_station_name = None

arrival_station_name class-attribute instance-attribute

arrival_station_name = None

for_return_leg

for_return_leg(departure_date, departure_time='000000')

왕복의 오는열차 검색 질의를 만듭니다 — 출발역과 도착역을 뒤집습니다.

앱이 오는열차를 다시 검색할 때 하는 것과 같습니다. 역을 맞바꾸고 dptDt1/dptTm1 대신 back_dptDt1/back_dptTm1 로 찾습니다 (ara1001l.js:110-115, fn_searchfv_sRtnCd == "2" 가지). 인원· 열차그룹·좌석속성은 그대로 따라갑니다.

SRT 의 왕복은 요청 하나에 여정 둘이 아닙니다. 평범한 편도 검색 둘과 평범한 편도 예약 둘이며(reserve 참고), 두 번째를 "오는" 것으로 만드는 것은 역이 뒤집혀 있다는 사실과 양쪽 예약이 rtnDv=1 을 싣는다는 것뿐입니다.

departure_time 기본값이 "000000" 인 것도 앱을 따른 것입니다 (back_dptTm1 의 초기값, ara0101v.js:111). 돌아오는 날 자정부터 훑어야 후보가 다 보이기 때문입니다.

날짜·시각의 앞뒤는 검사하지 않습니다. 앱은 오는 날이 가는 날보다 이르거나 같은 날인데 시각이 이르면 막지만(ara0101v.js:593-603) 그것은 이 라이브러리가 그리지 않는 폼 위의 대화상자입니다.

TrainSummary dataclass

TrainSummary(train_no, train_group_code=None, service_class_code=None, run_date=None, departure_date=None, departure_time=None, arrival_date=None, arrival_time=None, departure_station_code=None, arrival_station_code=None, raw=dict(), departure_station_name=None, arrival_station_name=None, departure_run_order=None, arrival_run_order=None, seat_attr_code=None, run_time=None, train_run_order=None, departure_consist_order=None, arrival_consist_order=None, current_delay=None, expected_delay=None, general_seat_availability=None, special_seat_availability=None, reservation_wait_availability=None, standing_availability=None, general_seat_availability_name=None, special_seat_availability_name=None, reservation_wait_availability_name=None, standing_availability_name=None, received_amount=None, discount_rate=None, received_fare=None, train_composition_codes=(), train_class_code=None, general_class_discount_rate=None, special_class_discount_rate=None)

train_no instance-attribute

train_no

train_group_code class-attribute instance-attribute

train_group_code = None

service_class_code class-attribute instance-attribute

service_class_code = None

run_date class-attribute instance-attribute

run_date = None

departure_date class-attribute instance-attribute

departure_date = None

departure_time class-attribute instance-attribute

departure_time = None

arrival_date class-attribute instance-attribute

arrival_date = None

arrival_time class-attribute instance-attribute

arrival_time = None

departure_station_code class-attribute instance-attribute

departure_station_code = None

arrival_station_code class-attribute instance-attribute

arrival_station_code = None

raw class-attribute instance-attribute

raw = field(default_factory=dict, repr=False)

departure_station_name class-attribute instance-attribute

departure_station_name = None

arrival_station_name class-attribute instance-attribute

arrival_station_name = None

departure_run_order class-attribute instance-attribute

departure_run_order = None

arrival_run_order class-attribute instance-attribute

arrival_run_order = None

seat_attr_code class-attribute instance-attribute

seat_attr_code = None

run_time class-attribute instance-attribute

run_time = None

train_run_order class-attribute instance-attribute

train_run_order = None

departure_consist_order class-attribute instance-attribute

departure_consist_order = None

arrival_consist_order class-attribute instance-attribute

arrival_consist_order = None

current_delay class-attribute instance-attribute

current_delay = None

expected_delay class-attribute instance-attribute

expected_delay = None

general_seat_availability class-attribute instance-attribute

general_seat_availability = None

special_seat_availability class-attribute instance-attribute

special_seat_availability = None

reservation_wait_availability class-attribute instance-attribute

reservation_wait_availability = None

standing_availability class-attribute instance-attribute

standing_availability = None

general_seat_availability_name class-attribute instance-attribute

general_seat_availability_name = None

special_seat_availability_name class-attribute instance-attribute

special_seat_availability_name = None

reservation_wait_availability_name class-attribute instance-attribute

reservation_wait_availability_name = None

standing_availability_name class-attribute instance-attribute

standing_availability_name = None

received_amount class-attribute instance-attribute

received_amount = None

discount_rate class-attribute instance-attribute

discount_rate = None

received_fare class-attribute instance-attribute

received_fare = None

train_composition_codes class-attribute instance-attribute

train_composition_codes = ()

train_class_code class-attribute instance-attribute

train_class_code = None

general_class_discount_rate class-attribute instance-attribute

general_class_discount_rate = None

special_class_discount_rate class-attribute instance-attribute

special_class_discount_rate = None

TransferItinerary dataclass

TransferItinerary(first_leg, second_leg)

환승 여정 — 선행 열차와 후행 열차를 한 쌍으로 묶은 것.

SRT 의 환승은 여정 슬롯 두 개를 실은 예약 하나입니다. 앱의 환승 토글이 jrnyTpCd="14"(환승편도)와 jrnyCnt="2"를 한 번에 씁니다 (ara0101v.js:302-303). jrnyCnt="2" 를 쓰는 자리는 번들 전체에서 여기 하나뿐이라 그 값은 곧 환승을 뜻합니다. 왕복은 "1" 그대로에 예약이 둘입니다.

first_leg 가 선행(jrnySqno1="001"), second_leg 가 후행(jrnySqno2="002")입니다(ara0101v.js:97).

이 타입이 검색 결과의 절반짜리 행을 예약 폼에 넘기는 실수를 방지합니다. reserve_transfer 는 이 타입만 받습니다.

생성 시점 검사: 두 열차 모두 TrainSummary, 선행 도착역 == 후행 출발역, 후행이 선행 도착보다 먼저 출발 불가, 같은 열차 불가.

환승 예약은 2026-07-31 실서버에서 확인됐습니다 — 동대구→목포, 열차 304 + 653, 오송 환승, SUCC/IRR000018. 단, 조회 결과에는 구간이 코레일 열차인 여정이 섞여 오고 그런 여정은 예약 폼이 거절합니다. 양쪽 TrainSummary.service_class_code"17" 인지 보고 고르십시오.

first_leg instance-attribute

first_leg

second_leg instance-attribute

second_leg

transfer_station_code property

transfer_station_code

두 구간이 만나는 환승역 코드. 생성 시점에 양쪽이 같음을 검사했습니다.

origin_station_code property

origin_station_code

destination_station_code property

destination_station_code

legs property

legs

두 구간을 여정 순서대로 — 선행이 앞, 후행이 뒤.

UnpairedTransferGroup dataclass

UnpairedTransferGroup(itinerary_no, rows, reason)

환승 검색이 준 행 중 여정으로 묶이지 못한 것들.

버리지 않고 남깁니다. 쌍을 짓는 것은 서버가 아니라 이 라이브러리의 추론입니다 — 서버는 납작한 행 목록을 주고 trnOrdrNo 로 묶는 것은 이쪽입니다. 추론이 맞지 않을 때 그 행들은 호출자가 볼 수 있는 곳에 있어야 하기 때문입니다.

reason 은 코드가 아니라 문장입니다. 실제로 관측한 적 없는 상황들이라 코드 어휘를 만들면 지어낸 것이 됩니다.

itinerary_no instance-attribute

itinerary_no

rows instance-attribute

rows

reason instance-attribute

reason

TrainSearchMetadata dataclass

TrainSearchMetadata(message_code, status, query_count, has_following_page=None, message='', raw=dict())

message_code instance-attribute

message_code

status instance-attribute

status

query_count instance-attribute

query_count

has_following_page class-attribute instance-attribute

has_following_page = None

message class-attribute instance-attribute

message = field(default='', repr=False)

raw class-attribute instance-attribute

raw = field(default_factory=dict, repr=False)

TrainSearchResult dataclass

TrainSearchResult(trains, result=dict(), raw=dict(), metadata=None)

trains instance-attribute

trains

result class-attribute instance-attribute

result = field(default_factory=dict, repr=False)

raw class-attribute instance-attribute

raw = field(default_factory=dict, repr=False)

metadata class-attribute instance-attribute

metadata = None

TransferSearchResult dataclass

TransferSearchResult(itineraries, unpaired, search)

환승 검색 결과 — 묶인 여정, 남은 행, 그리고 손대지 않은 원본.

응답 모양은 확인됐습니다. 환승 검색은 구간마다 한 행씩을 평범한 dsOutput1 목록에 담아 주고 — 직통 행과 열 구성이 같습니다 — 한 여정에 속하는 행들은 trnOrdrNo 를 공유합니다. 동대구(0015) -> 광주송정(0036) 에서 서버가 준 10 행이 그랬습니다: trnOrdrNo=1 은 382 열차 동대구->오송 과 411 열차 오송->광주송정 하는 식입니다. 모든 행이 chtnDvCd="2" 를 달고 있었고 fllwPgExt2null 이었습니다.

즉 여기서 trnOrdrNo 는 목록 안의 열차 순번이 아니라 여정 번호입니다. ...2 로 끝나는 열들도 모든 행에 있기는 하지만 전부 빈 문자열입니다 (trnNo2: "", dptRsStnCd2: "", jrnySqno: "") — 후행 구간은 열이 아니라 별도의 행이기 때문입니다.

itineraries 는 깨끗이 묶인 것, unpaired 는 묶이지 못한 것이며 각각 이유가 붙어 있습니다. 여정 개수만으로는 빠진 것이 있는지 알 수 없으니 빠짐없이 보려면 그쪽도 읽어야 합니다. search 는 손대지 않은 TrainSearchResult 라 원본 행과 원본 JSON 으로 언제든 되돌아갈 수 있습니다.

itineraries instance-attribute

itineraries

unpaired instance-attribute

unpaired

search instance-attribute

search

rows property

rows

서버가 준 행 전부 — 묶기 전, 서버가 준 순서 그대로.

raw property

raw

응답 본문 전체 — 받은 그대로.

MutualVerificationResult dataclass

MutualVerificationResult(message_code, status, message='', verification_code='', raw=dict())

message_code instance-attribute

message_code

status instance-attribute

status

message class-attribute instance-attribute

message = field(default='', repr=False)

verification_code class-attribute instance-attribute

verification_code = field(default='', repr=False)

raw class-attribute instance-attribute

raw = field(default_factory=dict, repr=False)

ReservationRecord dataclass

ReservationRecord(pnr_number, journey_list_key, arrival_date, arrival_station_code, arrival_time, delay_acceptance_flag, departure_date, departure_station_code, departure_time, lump_settlement_target_number, provisional_settlement_target_flag, service_class_code, total_seat_count, train_group_code, train_number, raw=dict())

pnr_number class-attribute instance-attribute

pnr_number = field(repr=False)

journey_list_key class-attribute instance-attribute

journey_list_key = field(repr=False)

arrival_date instance-attribute

arrival_date

arrival_station_code instance-attribute

arrival_station_code

arrival_time instance-attribute

arrival_time

delay_acceptance_flag instance-attribute

delay_acceptance_flag

departure_date instance-attribute

departure_date

departure_station_code instance-attribute

departure_station_code

departure_time instance-attribute

departure_time

lump_settlement_target_number class-attribute instance-attribute

lump_settlement_target_number = field(repr=False)

provisional_settlement_target_flag instance-attribute

provisional_settlement_target_flag

service_class_code instance-attribute

service_class_code

total_seat_count instance-attribute

total_seat_count

train_group_code instance-attribute

train_group_code

train_number instance-attribute

train_number

raw class-attribute instance-attribute

raw = field(default_factory=dict, repr=False)

ReservationTrain dataclass

ReservationTrain(seat_number, car_number, raw=dict())

seat_number class-attribute instance-attribute

seat_number = field(repr=False)

car_number class-attribute instance-attribute

car_number = field(repr=False)

raw class-attribute instance-attribute

raw = field(default_factory=dict, repr=False)

ReservationAttemptResult dataclass

ReservationAttemptResult(message_code, status, total_received_amount, reservation, train, message, temporary_job_sequence, command, raw)

message_code instance-attribute

message_code

status instance-attribute

status

total_received_amount instance-attribute

total_received_amount

reservation instance-attribute

reservation

train instance-attribute

train

message class-attribute instance-attribute

message = field(repr=False)

temporary_job_sequence class-attribute instance-attribute

temporary_job_sequence = field(repr=False)

command class-attribute instance-attribute

command = field(repr=False)

raw class-attribute instance-attribute

raw = field(repr=False)

SrtReservationHold dataclass

SrtReservationHold(pnr_no, journey_list_key='', total_seat_count='', journey_count='1', raw=dict())

예약은 됐지만 아직 결제되지 않은 상태 — 실제로 전송된 reserve 의 결과.

핵심은 pnr_no 입니다. 뒤이어 취소하거나 결제할 때 이 예약을 가리키는 이름이고, srtgo 도 성공한 예약에서 같은 값을 챙깁니다(reservListMap[0].pnrNo, srt.py:1006). pnr_nojourney_list_key 는 비밀에 준하므로 repr 에 나오지 않습니다 — 값을 보려면 속성을 직접 읽어야 합니다.

dry-run 예약은 이것을 만들지 않습니다. 그쪽은 MutationPreview 를 돌려줍니다.

pnr_no class-attribute instance-attribute

pnr_no = field(repr=False)

journey_list_key class-attribute instance-attribute

journey_list_key = field(default='', repr=False)

total_seat_count class-attribute instance-attribute

total_seat_count = ''

journey_count class-attribute instance-attribute

journey_count = '1'

raw class-attribute instance-attribute

raw = field(default_factory=dict, repr=False)

SrtReservationSummary dataclass

SrtReservationSummary(pnr_no, received_amount=None, ticket_special_number=None, seat_number=None, service_class_code=None, train_no=None, departure_date=None, departure_time=None, departure_station_code=None, arrival_time=None, arrival_station_code=None, payment_limit_date=None, payment_limit_time=None, settlement_flag=None, raw_train=dict(), raw_pay=dict())

One row of the 예약/발권 목록 (/atc/selectListAtc14016_n.do).

한 행은 서버가 따로 보낸 두 목록을 인덱스로 짝지어 만듭니다 — trainListMap[i](여정 정보)와 payListMap[i](결제 상태). srtgo 도 이 엔드포인트를 그렇게 읽습니다(srt.py:1069-1082).

필수인 것은 pnr_no 하나입니다. cancelscripts/recover_hold.py 가 쓰는 식별자입니다. 나머지는 전부 선택이고 기본값이 None 인데, 행이 채워진 응답을 본 적이 없기 때문입니다 — 확인에 쓴 계정에 예약이 없어서 trainListMap/payListMap 이 빈 배열로만 왔습니다.

그래서 아래 필드명의 출처가 갈립니다. payListMap, tkSpecNum, iseLmtTm, stlFlg 는 v2.0.41 번들에서 0회이고 srtgo 의 실제 전송 기록에만 있습니다. iseLmtDt, rcvdAmt, seatNum, pnrNo, rsvChgTno, jrnyCnt 는 승차권 확인 페이지의 인라인 스크립트에 나옵니다(gotoDetailARD02018(...), gotoDetailARD0201V(...)) — 이름은 앱이 뒷받침하지만 그것이 위 두 목록 중 어디에 들어가는지는 아닙니다.

따라서 None 은 "그 예약에 그런 값이 없다"가 아니라 "서버가 이 이름으로 보내지 않았다"로 읽어야 합니다. 실제로 온 것은 raw_train / raw_pay 에 있습니다.

pnr_no class-attribute instance-attribute

pnr_no = field(repr=False)

received_amount class-attribute instance-attribute

received_amount = None

ticket_special_number class-attribute instance-attribute

ticket_special_number = None

seat_number class-attribute instance-attribute

seat_number = field(default=None, repr=False)

service_class_code class-attribute instance-attribute

service_class_code = None

train_no class-attribute instance-attribute

train_no = None

departure_date class-attribute instance-attribute

departure_date = None

departure_time class-attribute instance-attribute

departure_time = None

departure_station_code class-attribute instance-attribute

departure_station_code = None

arrival_time class-attribute instance-attribute

arrival_time = None

arrival_station_code class-attribute instance-attribute

arrival_station_code = None

payment_limit_date class-attribute instance-attribute

payment_limit_date = None

payment_limit_time class-attribute instance-attribute

payment_limit_time = None

settlement_flag class-attribute instance-attribute

settlement_flag = None

raw_train class-attribute instance-attribute

raw_train = field(default_factory=dict, repr=False)

raw_pay class-attribute instance-attribute

raw_pay = field(default_factory=dict, repr=False)

SrtReservationListResult dataclass

SrtReservationListResult(reservations, status, message_code='', message='', row_count=None, total_page_count=None, raw=dict())

파싱된 예약/발권 목록과 서버가 함께 보낸 봉투.

예약이 없는 계정은 빈 reservations 이지 예외가 아닙니다. 빈 열차 검색과 다릅니다 — 검색은 없음을 strResult=FAIL / WRG000000 으로 선언하지만, 이 엔드포인트는 resultMap[0].strResult="SUCC" / IRZ000005 / "조회할 자료가 없습니다." 에 진짜로 빈 배열을 줍니다. 같은 응답의 두 번째 봉투 (rsMap)는 FAIL 이라고 말하는데 그것을 실패로 읽지 않는 이유는 parse_reservation_list_response 에 있습니다.

row_count / total_page_countrowCnt / totPageCnt 이며 JSON 정수로 옵니다(빈 응답에서는 둘 다 0). 없으면 None 입니다.

reservations instance-attribute

reservations

status instance-attribute

status

message_code class-attribute instance-attribute

message_code = ''

message class-attribute instance-attribute

message = field(default='', repr=False)

row_count class-attribute instance-attribute

row_count = None

total_page_count class-attribute instance-attribute

total_page_count = None

raw class-attribute instance-attribute

raw = field(default_factory=dict, repr=False)

pnr_numbers property

pnr_numbers

목록에 든 PNR 전부, 서버가 준 순서대로.

PNR 을 잃어버렸을 때 행 구조를 몰라도 되찾을 수 있게 하는 것이 용도입니다. scripts/recover_hold.py --list 가 출력하는 것이 정확히 이 값입니다.

SrtCancelResult dataclass

SrtCancelResult(status, message_code='', message='', raw=dict())

미결제 예약취소의 응답 봉투.

SRT 의 일반적인 resultMap 봉투이고 strResult == "SUCC" 면 성공입니다. 여정 한 건짜리 미결제 예약을 실제로 취소했을 때 SUCC / IRG000000 이 왔습니다.

업무상 실패는 예외가 아니라 데이터로 옵니다succeededFalse 이고 서버의 message_code 가 그대로 실립니다.

messageraw 는 원본 봉투가 예약 식별자를 되울려 주므로 repr 에서 빠집니다.

경로 자체는 srtgo 에서 왔고 v2.0.41 번들에서 0회입니다. 봉투 처리를 느슨하게 둔 이유는 parse_unpaid_cancel_response 에 있습니다.

status instance-attribute

status

message_code class-attribute instance-attribute

message_code = ''

message class-attribute instance-attribute

message = field(default='', repr=False)

raw class-attribute instance-attribute

raw = field(default_factory=dict, repr=False)

succeeded property

succeeded

SrtPaymentCard dataclass

SrtPaymentCard(card_number, card_password, card_validation_number, card_expire_date, installment_months=0, card_type='J')

카드결제가 실어 보내는 카드 필드 — 나가기 전에 모양을 검사합니다.

여기 넣은 값은 실제로 전송될 수 있습니다. payment 는 라이브 범주이므로 pay_with_carddry_run=False 와 분명한 카드 종류 주장이 붙으면 이 카드로 청구됩니다. 기본값은 마스킹된 미리보기이고, CARD_SECRET_FIELDS 가 결제 경로가 아닌 모든 경로에서 이 네 이름을 막습니다.

필드가 무엇을 담는지가 이름만으로는 헷갈리는 자리입니다.

  • card_password 는 카드 비밀번호 앞 두 자리입니다. 전체가 아닙니다.
  • card_type"J"(개인)냐 "S"(법인)냐가 card_validation_number 의 뜻을 결정합니다 — "J"YYMMDD 생년월일, "S" 면 열 자리 사업자등록번호입니다.
  • card_expire_dateYYMM.

비밀 네 개(card_number, card_password, card_validation_number, card_expire_date)는 repr=False 인 동시에 각자의 이름으로 SENSITIVE_KEYS 에 올라 있어서 repr()redact_value 양쪽에서 가려집니다. 패턴이 아니라 이름으로 가리는 이유는 CARD_RE 가 13~19 자리 숫자열만 잡아서 두 자리 비밀번호도, YYMM 도, YYMMDD 도 다 빠져나가기 때문입니다.

installment_monthscard_type 은 비밀이 아니라 일부러 가리지 않습니다. 다만 이 둘의 전송용 이름 ismtMnthNum1/athnDvCd1SENSITIVE_KEYS 에 있으므로 MutationPreview 에서는 가려집니다.

카드번호가 진짜인지는 검사하지 않습니다. 자릿수와 숫자 여부만 봅니다. Luhn 검사를 넣으면 합성 테스트 카드를 만들 수 없게 되고, 무엇보다 이 라이브러리가 어떤 카드번호가 유효한지 알려 주는 물건이 됩니다.

card_number class-attribute instance-attribute

card_number = field(repr=False)

card_password class-attribute instance-attribute

card_password = field(repr=False)

card_validation_number class-attribute instance-attribute

card_validation_number = field(repr=False)

card_expire_date class-attribute instance-attribute

card_expire_date = field(repr=False)

installment_months class-attribute instance-attribute

installment_months = 0

card_type class-attribute instance-attribute

card_type = 'J'

SrtPaymentResult dataclass

SrtPaymentResult(status, message_code='', message='', raw=dict())

카드결제의 응답 봉투.

succeededfailed 는 서로의 부정이 아닙니다. 그것이 이 타입의 요점입니다. 결제에서는 양쪽 오판이 다 비싸므로 모르는 상태값에 대해 판단하지 않습니다.

"SUCC""FAIL" 도 아닌 상태는 모름입니다. raw 를 읽고, 카드가 실제로 청구됐는지 다른 경로로 확인해야 하며, 무턱대고 재시도하면 안 됩니다 — 다시 보낸 결제는 두 번 청구될 수 있습니다.

확인된 두 가지는 실제 결제의 SUCC / IRT000000 과 가짜 카드의 FAIL / WRT100170 입니다. 경로 Ata09036 은 v2.0.41 오프라인 디컴파일 21,673 개 파일 전체에서 0회이고 앱은 이 경로를 쓰지 않습니다 — 경로도 본문도 이 봉투 모양도 참조 구현들의 실제 전송에만 근거가 있습니다 (parse_card_payment_response 참고).

status instance-attribute

status

message_code class-attribute instance-attribute

message_code = ''

message class-attribute instance-attribute

message = field(default='', repr=False)

raw class-attribute instance-attribute

raw = field(default_factory=dict, repr=False)

succeeded property

succeeded

failed property

failed

SrtRefundTicketInfo dataclass

SrtRefundTicketInfo(pnr_no, sale_date='', sale_window_number='', sale_sequence_number='', return_password='', buyer_name='', raw=dict())

환불에 필요한 발권 승차권 식별정보 — 환불 1단계의 결과.

POST /atc/getListAtc14087.do(본문 없음, PNR 은 Referer)의 outDataSets.dsOutput1[0] 에서 읽습니다 — 여기만 dsOutput1 이고, 다른 읽기는 전부 dsOutput0 을 씁니다.

return_password 가 환불을 승인하는 자격증명이라 repr 에서 빠지고, buyer_name·pnr_no 와 함께 redact_payload 에서도 가려집니다. 판매 식별자 셋 (sale_date, sale_window_number, sale_sequence_number)은 일부러 가리지 않습니다 — 비밀번호가 가려진 이상 그것만으로는 아무것도 승인하지 못하기 때문입니다.

이 경로는 참조 구현 하나에만 있습니다. 자세한 내력은 parse_refund_ticket_info_response 참고.

pnr_no class-attribute instance-attribute

pnr_no = field(repr=False)

sale_date class-attribute instance-attribute

sale_date = ''

sale_window_number class-attribute instance-attribute

sale_window_number = ''

sale_sequence_number class-attribute instance-attribute

sale_sequence_number = ''

return_password class-attribute instance-attribute

return_password = field(default='', repr=False)

buyer_name class-attribute instance-attribute

buyer_name = field(default='', repr=False)

raw class-attribute instance-attribute

raw = field(default_factory=dict, repr=False)

SrtRefundResult dataclass

SrtRefundResult(status, message_code='', message='', raw=dict())

발권된 승차권 환불의 응답 봉투.

봉투는 SRT 의 평범한 resultMap SUCC/FAIL 입니다 — 예약취소와 같고, 결제의 outDataSets.dsOutput0 과는 다릅니다.

업무상 실패는 예외가 아니라 값으로 돌아옵니다. 실제 승차권 환불에서 SUCC / IRT200277 이 왔습니다.

경로는 참조 구현 하나에만 있고, v2.0.41 오프라인 디컴파일 21,673 개 파일 전체에서 0회입니다.

status instance-attribute

status

message_code class-attribute instance-attribute

message_code = ''

message class-attribute instance-attribute

message = field(default='', repr=False)

raw class-attribute instance-attribute

raw = field(default_factory=dict, repr=False)

succeeded property

succeeded

HtmlPage dataclass

HtmlPage(text, raw)

text class-attribute instance-attribute

text = field(repr=False)

raw class-attribute instance-attribute

raw = field(repr=False)

SeatCarOption dataclass

SeatCarOption(car_number, label, available_seat_count=None)

좌석 페이지가 고르라고 내놓은 호차 하나와 그 호차의 잔여석 수.

페이지의 <select id="selectScarNo"> 에서 읽습니다 — 좌석 페이지가 들고 있는 재고 정보는 그것뿐입니다. 좌석배치도는 이 응답에 없습니다. 실제 페이지도 <div id="trnScarSeatInfo"> 를 비워 두고, 호차를 고른 뒤에 배치도를 따로 가져옵니다(get_seat_grid).

car_number instance-attribute

car_number

label instance-attribute

label

available_seat_count class-attribute instance-attribute

available_seat_count = None

SeatSelectionPage dataclass

SeatSelectionPage(text, raw, cars=())

Bases: HtmlPage

cars class-attribute instance-attribute

cars = ()

SeatGridSeat dataclass

SeatGridSeat(internal_seat_number, printed_seat_label, seat_attribute_code='', selectable=False)

좌석배치도의 좌석 한 칸 — 그 좌석의 이름 두 개를 다 들고 있습니다.

/arc/selectListArc02011_n.do 가 주는 배치도의 각 칸이 이런 요소입니다::

<div role="text" tabindex="0" aria-label="1C" id="scarSeat_1C"
     class="seatChoice015Y"
     onclick="choiceSeatNo('3', '1C', 'Y');"><span>1C</span></div>

좌석에는 이름이 둘 있고 서로 바꿔 쓸 수 없습니다. choiceSeatNo 의 첫 인자는 호차 안에서 1, 2, 3, 4, 5 … 로 이어지는 내부 좌석번호 (internal_seat_number)이고, 둘째 인자는 승객이 좌석에서 읽는 인쇄 좌석명(printed_seat_label, 1A, 1B, 1C, 1D, 2A …)입니다. 위 칸에서 내부 3 번의 인쇄명이 1C 입니다. 요소의 idaria-label 은 인쇄명으로 만들어집니다.

예약 폼이 받는 것은 인쇄 좌석명입니다. 앱의 좌석선택 콜백은 {scarSeatNo: "2,7,10", scarSeatNm: "1B,2C,3B", scarNo: 1} 로 둘 다 받아 놓고, seatNo1_1..N 을 인쇄명 쪽인 scarSeatNm 으로 채우며 scarSeatNo 는 버립니다(ara0101v.js:868-878). 이것은 번들 근거이고 실제 전송으로 확인된 것은 아닙니다(personal_reservation_payload 참고).

seat_attribute_code 는 칸의 class(seatChoice<코드><Y|N>)에 박힌 좌석속성코드입니다. 한 호차 안에 000, 015, 021, 028 이 모두 나타났습니다. selectablechoiceSeatNo 의 셋째 인자가 Y 인지이며, N 칸도 그려지지만 고를 수 없습니다.

internal_seat_number instance-attribute

internal_seat_number

printed_seat_label instance-attribute

printed_seat_label

seat_attribute_code class-attribute instance-attribute

seat_attribute_code = ''

selectable class-attribute instance-attribute

selectable = False

SeatDesignation dataclass

SeatDesignation(car_number, seats, cabin_class='')

호차 하나에서 호출자가 고른 좌석들 — 낱개가 아니라 묶음으로 검사됩니다.

reserve(..., designated_seats=…) 가 받는 타입입니다. 손으로 만들지 말고 SeatGrid.choose 로 배치도에서 만드는 편이 좋습니다 — 그래야 좌석명이 서버가 준 것이고 선택 가능 여부도 대조할 대상이 있습니다.

생성 시점에 다음을 검사합니다.

  • 좌석이 최소 하나, 전부 정확히 SeatGridSeat,
  • 모든 좌석이 selectableN 칸은 서버가 그려는 주지만 받지는 않습니다,
  • 같은 인쇄 좌석명이 두 번 나오지 않음(한 좌석이 인원 슬롯 둘을 먹고 한 사람이 좌석 없이 남습니다),
  • 호차 번호가 숫자만 — scarNo1 로 그대로 나가는 값입니다.

인원수와 좌석수가 맞는지는 여기서 보지 않습니다. 그 검사는 승차인원을 알아야 하므로 양쪽이 다 보이는 personal_reservation_payload 에 있습니다.

car_number instance-attribute

car_number

seats instance-attribute

seats

cabin_class class-attribute instance-attribute

cabin_class = ''

printed_seat_labels property

printed_seat_labels

seatNo1_1..N 으로 나갈 순서 그대로의 인쇄 좌석명.

SeatGrid dataclass

SeatGrid(text, raw, car_number='', seats=(), cabin_class='')

Bases: HtmlPage

열차 하나, 호차 하나의 파싱된 좌석배치도.

car_number요청할 때 지목한 호차입니다. 이 라이브러리가 scarNo 로 보낸 값이지 응답에서 읽은 값이 아닙니다 — 배치도 조각은 자기가 몇 호차인지 말하지 않습니다. seats 는 고를 수 있든 없든 문서 순서대로의 모든 칸입니다.

좌석을 지정하려면 chooseSeatDesignation 을 만들면 됩니다.

car_number class-attribute instance-attribute

car_number = ''

seats class-attribute instance-attribute

seats = ()

cabin_class class-attribute instance-attribute

cabin_class = ''

selectable_seats property

selectable_seats

choose

choose(*printed_seat_labels)

인쇄 좌석명("1C", "2A" …)으로 좌석을 지정합니다.

승객이 좌석에서 읽는 이름이자 예약 폼이 실제로 실어 보내는 이름이라 (ara0101v.js:868-878) 이 인자를 받습니다. 내부 좌석번호가 아닙니다.

없는 좌석명은 조용히 버리지 않고 ValueError 입니다. 오타 하나가 일행의 좌석 수를 소리 없이 줄이지 않게 하려는 것이고, 오류 메시지에 고를 수 있는 좌석명이 함께 나옵니다.

PublicDiscountEntitlement dataclass

PublicDiscountEntitlement(code, name='', approved=False)

공공할인 한 종류와, 이 계정이 그것을 승인받았는지.

codePBL_DISC_CD("01"~"08")이고, namepublic_discount_name 이 풀어 준 이름입니다. 07, 08 은 페이지에 분기는 있는데 이름이 어디에도 없어서 "" 입니다.

코드와 슬롯의 대응은 추론입니다. 페이지는 data1Check 부터 data8Check 까지 여덟 개의 플래그를 렌더링해 주면서 그 옆에 PBL_DISC_CD 를 한 번도 적지 않습니다. 둘을 잇는 근거는 두 플래그를 한꺼번에 읽는 유일한 분기에 페이지가 직접 단 주석뿐입니다 — if(data1Check == "Y" && data2Check == "Y") 위의 "다자녀(01)와 임산부(02)가 신청이 승인된 경우". 플래그도 코드도 정확히 여덟 개이고, 아래쪽의 여덟 개 PBL_DISC_CD 분기가 01~08 순서로 늘어서 있습니다. 나머지 여섯의 대응은 이것과 어긋나는 근거도, 뒷받침하는 근거도 없습니다.

code instance-attribute

code

name class-attribute instance-attribute

name = ''

approved class-attribute instance-attribute

approved = False

PublicDiscountPage dataclass

PublicDiscountPage(text, raw, entitlements=())

Bases: HtmlPage

할인 승차권 페이지를 "이 계정이 어떤 공공할인을 가졌나"로 읽은 것.

아무것도 승인받지 못한 계정은 오류가 아니라 답입니다. 그 경우 페이지는 Sr.msgs.notice006("할인승차권은 홈페이지를 통해 인증된 고객만 이용이 가능합니다…")을 띄우고 메인으로 돌려보내지만, "가진 것이 없다"가 곧 물어본 것에 대한 답이라 그대로 돌려줍니다 — is_eligibleFalse 이고 entitlements 의 모든 행이 approved=False 입니다.

담지 않는 것: 승인된 할인의 관리번호(PBL_DISC_MG_NO)와 확인·만료 날짜. 그 값들은 페이지의 if/else if 분기 본문 안에 서버가 렌더링해 넣는데, 읽을 수 있었던 계정에서는 여덟 분기가 전부 비어 있었습니다. 승인된 계정을 가진 호출자는 raw 에서 직접 읽을 수 있습니다.

entitlements class-attribute instance-attribute

entitlements = ()

approved property

approved

is_eligible property

is_eligible

승인된 공공할인이 하나라도 있으면 참.

페이지가 쓰는 조건 그대로입니다 — 여덟 플래그 중 하나라도 "Y" 면 검색 폼을 보여 주고, 아니면 거절합니다.

PublicDiscountSelection dataclass

PublicDiscountSelection(code, management_no='')

어떤 공공할인으로 검색할지 — 코드와 승인번호.

할인 승차권 검색에서 호출자가 채우는 쪽입니다. ajax 폼이 pblDiscCdpblDiscMgNo 로 싣는 두 값이고, 함께 가는 tgtDtrmYn 은 페이지가 늘 "Y" 로 두므로 선택지로 두지 않았습니다.

PublicDiscountEntitlement 와 타입을 나눈 것은 답하는 질문이 다르기 때문입니다 — 자격은 계정이 가진 것이고, 선택은 이번 검색이 무엇을 위한 것인지입니다.

code"01"~"08"PBL_DISC_CD 이고 public_discount_name 이 그중 여섯의 이름을 압니다.

management_no 는 값을 본 적이 없습니다. PBL_DISC_MG_NO 는 서버가 발급하는 승인번호로, 할인 승차권 페이지가 계정이 승인받은 할인의 분기 본문에 렌더링해 넣습니다. 승인이 없는 계정에서는 그 분기 본문이 전부 비어 있어 기본값이 "" 입니다 — 승인된 계정을 가진 호출자는 자기 PublicDiscountPage.raw 에서 읽어 넘기면 됩니다. 서버가 이 값을 요구하는지, 아니면 세션에서 알아내는지는 모릅니다.

인원수 제한은 여기서 검사하지 않습니다. 그것은 (코드, 인원) 쌍에 관한 사실이라 public_discount_search_payload 에 있습니다.

code instance-attribute

code

management_no class-attribute instance-attribute

management_no = ''

name property

name

공공할인의 한국어 이름. 07/08 은 이름이 없어 "" 입니다.

DiscountCoupon dataclass

DiscountCoupon(coupon_number='', discount_kind='', discount_rate='', validity='', basis='', remaining_uses='')

계정이 가진 할인쿠폰 한 장 — 페이지가 찍어 준 글자 그대로.

모든 필드가 표시용 문자열이지 파싱된 값이 아닙니다. discount_rate"45%" 이고 remaining_uses"이용가능 횟수 : 1" 입니다. 숫자를 원하면 호출자가 직접 뽑아야 합니다.

그렇게 둔 이유는 채워진 행을 본 적이 없어서입니다. 빈 상태("보유한 쿠폰이 없습니다.")는 확인됐지만 쿠폰을 가진 계정이 없었습니다. 필드명의 근거는 쿠폰 페이지에 주석으로 남은 디자이너 템플릿이 전부입니다 — class 이름은 페이지의 것이고 값은 예시입니다::

<span class="rate">45%</span>
<span class="boarding">탑승일기준</span>
<span class="date">2099.01.01 ~ 2099.12.31</span>
<span class="type"> 운임할인</span>
<span class="num">9910000001</span>
<span class="useCnt">이용가능 횟수 : 1</span>

discount_kind 는 페이지가 맨 위에서 밝히는 두 갈래입니다 — 운임할인은 운임을, 특실할인은 특실 추가금을 깎습니다.

coupon_number class-attribute instance-attribute

coupon_number = ''

discount_kind class-attribute instance-attribute

discount_kind = ''

discount_rate class-attribute instance-attribute

discount_rate = ''

validity class-attribute instance-attribute

validity = ''

basis class-attribute instance-attribute

basis = ''

remaining_uses class-attribute instance-attribute

remaining_uses = ''

DiscountCouponList dataclass

DiscountCouponList(text, raw, coupons=())

Bases: HtmlPage

할인쿠폰조회/등록 페이지를 행으로 읽은 것.

쿠폰이 없는 계정은 빈 coupons 이지 파싱 실패가 아닙니다. 반대로 쿠폰도 없고 페이지 자신의 "보유한 쿠폰이 없습니다." 표시도 없는 응답은 빈 목록으로 여기 도달하지 못하고 파서가 거절합니다. 그래서 "가진 것이 없다"와 "이 페이지를 이해하지 못했다"가 절대 같아 보이지 않습니다.

coupons class-attribute instance-attribute

coupons = ()

is_empty property

is_empty

SrtCouponRegistrationRequest dataclass

SrtCouponRegistrationRequest(coupon_number, coupon_password)

할인쿠폰 등록 한 건 — 쿠폰번호와 쿠폰 비밀번호.

이 둘은 무기명 자격증명입니다. 번호와 비밀번호를 내미는 사람이 쿠폰을 쓰게 되고, 등록하는 계정은 그저 먼저 물어본 쪽일 뿐입니다. 그래서 두 속성명과 두 전송용 이름(dscp_no/dscp_pwd)이 모두 SENSITIVE_KEYS 에 있고, coupon_number 도 비밀번호와 나란히 repr=False 입니다. 일반 규칙으로는 둘 다 걸리지 않습니다: dscp_pwd 는 문자 그대로의 password 가 아니고, 열 자리 dscp_noCARD_RE 가 잡기에 짧습니다.

아래 두 제약은 /apa/selectListApa03020_n.do 페이지의 것입니다.

  • coupon_number<input type="number" name="dscp_no" maxlength="10"> 에 숫자가 아닌 것을 지우고 열 자리로 자르는 keyup 핸들러가 붙어 있습니다. 즉 숫자만, 1~10 자리.
  • coupon_password<input type="password" name="dscp_pwd" maxlength="4">. 네 글자까지이고 숫자로 제한하지 않습니다. 페이지가 강제하지 않는 문자 집합을 넘겨짚으면 앱이라면 받았을 쿠폰을 거절하게 됩니다.

빈 값은 페이지가 거절하는 것과 같은 이유로 여기서 거절합니다 (mysrt006/mysrt007, js/common/messages.js:111-112).

coupon_number class-attribute instance-attribute

coupon_number = field(repr=False)

coupon_password class-attribute instance-attribute

coupon_password = field(repr=False)

SrtCouponRegistrationResult dataclass

SrtCouponRegistrationResult(status, message='', raw=dict())

The parsed envelope of a 할인쿠폰 등록.

이 응답을 본 적이 없습니다. 아래 필드는 전부 쿠폰 페이지의 성공 핸들러에서 읽은 것이고, 이 라이브러리가 쿠폰 등록을 보낸 적은 없으며, 경로는 v2.0.41 오프라인 번들에서 0회입니다::

var msg   = args.resultMap[0].MSG;
var rtncd = args.resultMap[0].RTNCD;
if(rtncd == "N"){ ...show msg... } else { ...show mysrt008... }

봉투가 다릅니다. 다른 상태변경이 모두 strResult/msgCd/msgTxt 를 돌려주는 데 반해 이쪽은 resultMap[0] 에 대문자 RTNCD/MSG 입니다. 익숙한 모양으로 바꾸지 않고 페이지가 읽는 그대로 두었습니다.

succeeded 도 페이지의 극성을 그대로 따릅니다. "N" 만 실패이고 나머지는 전부 성공입니다. 그래서 파서가 비어 있거나 없는 RTNCD 를 따로 거절합니다. 이 규칙대로면 코드가 없는 응답이 성공으로 읽히기 때문입니다.

여기서 성공은 요청이 접수됐다는 뜻이지 쿠폰이 보인다는 뜻이 아닙니다. 페이지의 성공 문구가 그렇게 말합니다(mysrt008: "쿠폰등록 요청을 완료하였습니다 … 쿠폰등록이 지연 될 경우 입력하신 쿠폰이 바로 조회 되지 않을 수 있습니다"). 등록 직후 get_discount_coupons 를 불러 아무것도 보이지 않는 것은 정상일 수 있습니다.

messageraw 는 거절된 쿠폰번호가 되울려 나올 수 있어 repr 에서 빠집니다.

status instance-attribute

status

message class-attribute instance-attribute

message = field(default='', repr=False)

raw class-attribute instance-attribute

raw = field(default_factory=dict, repr=False)

FAILURE_CODE class-attribute instance-attribute

FAILURE_CODE = 'N'

succeeded property

succeeded

Notice dataclass

Notice(is_main, page_id, body, post_no=0, create_date='', is_notice='', subject='', raw=dict())

is_main instance-attribute

is_main

page_id instance-attribute

page_id

body class-attribute instance-attribute

body = field(repr=False)

post_no class-attribute instance-attribute

post_no = 0

create_date class-attribute instance-attribute

create_date = ''

is_notice class-attribute instance-attribute

is_notice = ''

subject class-attribute instance-attribute

subject = ''

raw class-attribute instance-attribute

raw = field(default_factory=dict, repr=False)

NoticeListResult dataclass

NoticeListResult(notices, raw=dict())

notices instance-attribute

notices

raw class-attribute instance-attribute

raw = field(default_factory=dict, repr=False)

TimetableRow dataclass

TimetableRow(station_name, times, raw_text, station_code='')

station_name instance-attribute

station_name

times instance-attribute

times

raw_text class-attribute instance-attribute

raw_text = field(repr=False)

station_code class-attribute instance-attribute

station_code = ''

TimetablePage dataclass

TimetablePage(text, raw, rows=())

Bases: HtmlPage

rows class-attribute instance-attribute

rows = ()

FareItem dataclass

FareItem(label, amount, raw_amount, available=True, status=None)

label instance-attribute

label

amount instance-attribute

amount

raw_amount instance-attribute

raw_amount

available class-attribute instance-attribute

available = True

status class-attribute instance-attribute

status = None

FarePage dataclass

FarePage(text, raw, items=(), semantic_items=())

Bases: HtmlPage

items class-attribute instance-attribute

items = ()

semantic_items class-attribute instance-attribute

semantic_items = ()

available_items property

available_items

SearchPageState dataclass

SearchPageState(hidden_fields=dict(), raw='')

hidden_fields class-attribute instance-attribute

hidden_fields = field(default_factory=dict, repr=False)

raw class-attribute instance-attribute

raw = field(default='', repr=False)