Repository navigation
feat: Streamlit 디버그 UI를 examples/streamlit_debug_ui.py 템플릿으로 통합 - #27
Merged
Merged
Conversation
khoa의 streamlit_debug_ui.py 템플릿에 맞춰 tools/debug_streamlit.py(780줄, operation별 하드코딩 분기, Fixture 탭 미구현, APIHub 470개 endpoint 전부 실행 불가)를 새로 짰다. - src/kma/debug.py 신설: DebugRun/jsonable/redact_sensitive/debug_error/ save_fixture — khoa의 debug.py 구조를 그대로 따른다. - ApiCatalogEntry에 required_params/optional_params/param_defaults/ response_kind/endpoint_path 메타데이터 필드를 추가하고, catalog.py에 apihub_endpoint_catalog()를 새로 만들어 APIHub 470개 endpoint를 실제 호출 가능한 카탈로그 row로 노출했다(기존 api_catalog()는 하위 호환 유지, 테스트 불변 확인됨). - DataGoKrClient.debug_fetch()/ApiHubClient.debug_fetch_endpoint() 제네릭 메서드 추가 — endpoint별 분기 없이 카탈로그가 넘겨주는 service/operation 또는 ApiHubEndpointSpec만으로 요청을 라우팅하고 구조화된 DebugRun을 반환한다(예외도 traceback 포함 구조화 dict로, redact_sensitive 통과). - examples/streamlit_debug_ui.py: Data source -> Category -> API 3단 계단식 사이드바, st.form() 기반 파라미터 폼을 카탈로그 메타데이터에서 자동 생성(하드코딩 if function_name== 분기 없음), 고정 6탭(Raw Response/ Pydantic Model/Processed Result/Validation Errors/Debug Trace/ Fixture-Testcase), 세션 상태는 gateway:dataset_id:service:operation으로 스코프해 데이터소스 전환 시 이전 결과가 섞이지 않게 했다. Fixture 탭은 save_fixture()를 실제로 호출해 파일을 저장한다. - pyproject.toml debug-ui extra에 pandas>=2 추가. Co-Authored-By: Claude Sonnet 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01XF9V2q4mAmhmXn6t5G9Hfe
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
요약
이번 세션에서 여러 저장소에 걸쳐 정한 표준 Streamlit 디버그 UI 템플릿(원본:
python-khoa-api의examples/streamlit_debug_ui.py+src/khoa/debug.py)에맞춰, 이 저장소의
tools/debug_streamlit.py(780줄, operation별 하드코딩if service == ...분기, Fixture 탭 미구현, APIHub 470개 endpoint 전부실행 불가)를 새로 짰습니다. 이 저장소는 카탈로그 규모(data.go.kr 160개
operation + APIHub 470개 endpoint = 630개+)가 다른 저장소보다 훨씬 커서,
완벽한 커버리지보다 3단 계단식 UI 골격 + 대표 엔드포인트가 실제로 동작하는
수준을 목표로 했습니다.
백엔드 선행 작업 (배경 격차 채우기)
src/kma/debug.py신설 — khoa의debug.py구조를 그대로 따라DebugRundataclass,jsonable(),redact_sensitive()(dict/list 재귀마스킹 + 문자열 값 내 credential query 패턴까지 이중으로 정리),
debug_error()({type, message, traceback}+KmaError면provider/endpoint/status_code/result_code/failure_kind/retryable 추가),
save_fixture()를 만들었습니다. 이전에는 이 패키지에 이런 공용 debug헬퍼가 전혀 없었습니다.
ApiCatalogEntry에 파라미터 메타데이터 필드 추가 —required_params/optional_params/param_defaults/response_kind/endpoint_path. 기존 필드/동작은 그대로 유지해api_catalog()를 쓰는기존 테스트(
len(rows) == 208등)는 전부 그대로 통과합니다.apihub_endpoint_catalog()신설 — APIHubapiList.do/generateAPIUrl.do에서 수집한 470개 endpoint(APIHUB_ENDPOINTS)를실행 가능한
ApiCatalogEntryrow로 노출합니다. 기존api_catalog()가반환하던 apihub "LINK" placeholder dataset(실행 불가, service/operation
없음)과는 별도 함수로 분리했습니다 — 섞으면 기존 dataset 카운트
테스트가 깨지고, 애초에 서로 다른 두 소스(data.go.kr 카탈로그 vs
APIHub 스크래핑 결과)라 의미도 다릅니다.
debug_fetch메서드 추가DataGoKrClient.debug_fetch(service, operation, params, ...)—기존
request_with_metadata()를 감싸 타이밍/trace/구조화 에러를붙이고, 성공하면 row를 실제
DataGoKrItemPydantic 모델로 검증까지한 뒤
DebugRun으로 반환합니다.ApiHubClient.debug_fetch_endpoint(spec, params)—ApiHubClient(hand-maintained 모듈)에 추가했습니다.
apihub_endpoints.py는tools/update_apihub_endpoints.py가 통째로 재생성하는 파일이라거기 있는
ApiHubGeneratedClient안에 직접 메서드를 추가하면 다음재생성 때 사라집니다 — 그래서 부모 클래스인
ApiHubClient에 추가해ApiHubGeneratedClient가 상속으로 그대로 받게 했습니다(재생성해도안전).
response_kind(structured/text/image/file)에 따라 raw/처리결과를 다르게 정리합니다.
if분기가 없습니다 — service/operation이름 또는
ApiHubEndpointSpec만으로 라우팅합니다. UI에서gateway두 값(datagokr/apihub)으로 어느 client를 쓸지 고르는 것은 이
패키지가 애초에 gateway별로 클라이언트 클래스가 분리돼 있기 때문이며,
khoa처럼 단일 서비스 레지스트리가 없어 불가피한 최소 분기입니다(PR
본문에 밝혀둡니다 — 고쳐야 할 안티패턴인 "operation별 분기"와는
다릅니다).
pyproject.toml의debug-uiextra에pandas>=2를 추가했습니다(기존에는
streamlit만 있었습니다).examples/streamlit_debug_ui.pydatagokr/apihub) → Category → API 3단계단식(
datagokr는 Category=dataset명,apihub는 Category=관측/예특보등 11개 분류). 선택한 API 설명 2줄, Environment(실제 env var 이름 표시)
vs 수동 입력, Auth(실제 파라미터명인
serviceKey/authKey입력창),서비스키 발급 링크, Timeout, Fixture 기본 디렉터리(
tests/fixtures기본st.form()으로 감싸고 카탈로그의required_params/optional_params/param_defaults에서 위젯을자동 생성합니다.
dataType/type처럼 고정 선택지가 있는 파라미터는selectbox, 나머지는 text input입니다(kma의
enums.py는 응답 값분류용이라 요청 파라미터로 재사용할 대상이 없었습니다 — 실제로
존재하는 고정 선택지만 selectbox로 구현했습니다). 폼에 없는 파라미터는
Extra params JSON으로 보충합니다.Validation Errors / Debug Trace / Fixture · Testcase. Processed
Result는 list 응답일 때만
pd.json_normalize로 dataframe을 보여주고단일 object면
st.json으로 배타적으로 표시합니다. Fixture ·Testcase 탭은 실제로
save_fixture()를 호출해tests/fixtures/<function>/<case>.json에 저장합니다 — 이전구현은 "별도 단계에서 연결합니다" 안내만 있는 완전 미구현 스텁이었습니다.
{gateway}:{dataset_id}:{service}:{operation}으로 스코프해서, 데이터소스를 전환하거나 사이드바(폼 밖) 위젯을 조작해 rerun이 나도 이전 결과가
섞이거나 사라지지 않습니다(kasi에서 발견됐던 버그 패턴을 처음부터
피하는 설계).
layout="wide"만 사용합니다.검증
python -m pytest -q -m "not integration"— 149 passed, 12deselected(이 저장소는
integrationmarker를 씁니다). 기존api_catalog()/ApiCatalogEntry관련 테스트를 포함해 전부 그대로통과합니다.
python -m ruff check .— 통과.python -m mypy src/kma— 통과(src/kma22개 파일, strict 모드).AppTest스모크 체크 —examples/streamlit_debug_ui.py를AppTest.from_file(...).run()으로 초기 렌더했고at.exception이비어 있음을 확인했습니다. 추가로 Data source/Category/API 위젯을
실제로 조작해(datagokr ↔ apihub 전환, category 변경) 재렌더해도
예외가 없음을 확인했고, 로컬
.env에 있는 실제 개발용 키로 폼을제출해
getUltraSrtNcst를 라이브로 호출 → 성공 응답 처리 → Fixture저장 버튼까지 눌러 실제로
tests/fixtures/...json파일이 생성되는것을 확인했습니다(스모크 테스트용으로 생성된 fixture 파일은 커밋
전에 삭제했습니다). 빈 인증값으로 제출했을 때도 크래시 없이 구조화된
에러가 표시되는 것을 확인했습니다.
커버하지 못한 부분 (정직하게 명시)
필수/선택 파라미터 명세가 있는 것은 **10개 service(약 30개
operation)**뿐입니다(단기예보, 중기예보, ASOS 일/시간자료, 기상특보,
관광지 날씨, 통보문, 생활기상지수, 지진정보, 해수욕장 날씨). 나머지
~130개 operation은 required_params/optional_params가 비어 있어
Extra params JSON으로 직접 파라미터를 채워야 합니다.response_kind가text인 legacy endpoint(다수)는parse_apihub_text_table()의 공백 기반 관대한 파싱을 그대로 쓰므로일부 endpoint에서 컬럼 정렬이 정확하지 않을 수 있습니다(예:
스모크 테스트에서
kma_sfctm2샘플 응답이STN컬럼에 여러 값이뭉쳐 들어감을 확인).
image/filekind는 내용을 해석하지 않고크기/타입 metadata만 보여줍니다.
apiList.do스크래핑)에는 어떤 파라미터가 진짜 필수인지 기록이 없어, 470개
전부
optional_params로 두고 실제 관찰된 sample 값으로 미리채웠습니다. 사용자가 값을 지우고 실행하면 API가 직접 오류를
돌려줍니다.
AsyncDataGoKrClient/AsyncApiHubClient용비동기
adebug_fetch는 만들지 않았습니다(Streamlit UI는 동기 호출만필요).
참고
python-khoa-api의examples/streamlit_debug_ui.py,src/khoa/debug.py