CI uv setup 실패 (#6 후속): - 원인: astral-sh/setup-uv@v3 의 enable-cache:true 가 **/uv.lock 미발견 시 fail. 7개 push 모두 ::error::No file ... matched to [**/uv.lock] → 10-20초 만에 abort. - 해결: uv.lock 생성 (438KB, 89 packages 해결) + cache-dependency-glob 명시. 연쇄 수정 (uv.lock 생성 과정에서 노출): - pyproject.toml: scipy/pyproj/numpy 핀을 hard-pin == 에서 range > = 로 완화 (base vs [py313] extras 충돌 해소). requires-python ">=3.9" → ">=3.11" (pyproj>=3.7 wheel 가용 환경과 일치). [tool.uv] no-progress = false 제거 (deprecated). - .gitea/workflows/ci.yml: 별도 Setup Python step 제거 (uv venv가 자동 fetch), install step 단순화 (matrix 분기 EXTRAS 변수), 모든 run: 에 shell: bash 명시. UI 진행률 인디케이터 (#4 부분): - self.progress_bar (CTkProgressBar mode=indeterminate, MC overlap orange #FF5F00) status_bar 우측에 hidden 배치. start_progress(label)/stop_progress() 메서드 추가. - self.textbox height 120 → 80 (인라인 로그 비중 축소, 백엔드 파일이 주 기록처). ruff cleanup (harness/perf.py): - Optional[Callable[...]] → Callable[...] | None (UP045). - try/except/pass → contextlib.suppress (SIM105). - 미사용 # noqa: BLE001 제거 (RUF100). 검증: uv lock 성공, ruff check All checks passed, py_compile + AST OK. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -37,25 +37,31 @@ jobs:
|
||||
uses: astral-sh/setup-uv@v3
|
||||
with:
|
||||
enable-cache: true
|
||||
|
||||
- name: Setup Python ${{ matrix.python-version }}
|
||||
run: uv python install ${{ matrix.python-version }}
|
||||
cache-dependency-glob: "uv.lock"
|
||||
|
||||
- name: Install deps
|
||||
shell: bash
|
||||
run: |
|
||||
uv venv .venv --python ${{ matrix.python-version }}
|
||||
uv pip install --python .venv -e ".[dev]"
|
||||
# Py3.13은 호환 핀 별도
|
||||
set -e
|
||||
if [ "${{ matrix.python-version }}" = "3.13" ]; then
|
||||
uv pip install --python .venv -e ".[py313,dev]"
|
||||
EXTRAS=".[py313,dev]"
|
||||
else
|
||||
EXTRAS=".[dev]"
|
||||
fi
|
||||
# uv 가 자동으로 Py 버전 fetch + .venv 생성. 별도 `uv python install`
|
||||
# step 불필요 (uv venv 가 내부적으로 처리).
|
||||
uv venv .venv --python ${{ matrix.python-version }}
|
||||
source .venv/bin/activate
|
||||
uv pip install -e "$EXTRAS"
|
||||
|
||||
- name: Ruff lint
|
||||
shell: bash
|
||||
run: |
|
||||
source .venv/bin/activate
|
||||
ruff check --output-format=github
|
||||
|
||||
- name: py_compile (전체 .py)
|
||||
shell: bash
|
||||
run: |
|
||||
source .venv/bin/activate
|
||||
python -c "
|
||||
@@ -74,6 +80,7 @@ jobs:
|
||||
"
|
||||
|
||||
- name: pytest (회귀)
|
||||
shell: bash
|
||||
run: |
|
||||
source .venv/bin/activate
|
||||
pytest -ra --tb=short -m "not slow and not integration"
|
||||
@@ -81,6 +88,7 @@ jobs:
|
||||
- name: pytest (slow + integration, allow failure)
|
||||
if: ${{ matrix.python-version == '3.13' }}
|
||||
continue-on-error: true
|
||||
shell: bash
|
||||
run: |
|
||||
source .venv/bin/activate
|
||||
pytest -ra --tb=short -m "slow or integration"
|
||||
|
||||
53
CHANGELOG.md
53
CHANGELOG.md
@@ -10,6 +10,59 @@
|
||||
|
||||
---
|
||||
|
||||
## 2026-05-08 (후속 — CI fix + UI 2차)
|
||||
|
||||
### [fix] Gitea CI uv setup 실패 — `**/uv.lock` 미존재 → setup-uv 액션 abort (#6 후속)
|
||||
|
||||
- **증상**: 7개 push 모두 CI run 10-20초 만에 `failure`. 로그:
|
||||
```
|
||||
::error::No file in /workspace/HYUNJUNGLEE/s-canvas matched to [**/uv.lock]
|
||||
❌ Failure - Main Setup uv (fast Python pkg manager)
|
||||
```
|
||||
- **원인**: `astral-sh/setup-uv@v3` 의 `enable-cache: true` 옵션이 cache key 산출용 `**/uv.lock` 검색 → 미발견 시 hard fail. UV_GUIDE.md §3 에서 권장만 했고 실제 lock 파일은 없었음.
|
||||
- **추가 발견 (uv.lock 생성 시도 시 노출)**:
|
||||
1. `[tool.uv] no-progress = false` — uv 0.11+ 가 모르는 옵션 (deprecated). 제거.
|
||||
2. **dependency 핀 충돌**: `dependencies` 의 `scipy==1.13.1` / `pyproj==3.6.1` vs `[py313]` extras 의 `scipy>=1.14` / `pyproj>=3.7,<4` — uv resolver 가 동시 만족 불가.
|
||||
3. `pyproj>=3.7` 가 Py3.11+ 만 wheel 배포 — `requires-python = ">=3.9"` 와 충돌.
|
||||
|
||||
#### 수정안 (5건)
|
||||
- **`.gitea/workflows/ci.yml`**:
|
||||
- `enable-cache: true` + `cache-dependency-glob: "uv.lock"` (lock 파일 변경 시에만 캐시 갱신).
|
||||
- 별도 `Setup Python` step 제거 — `uv venv --python <ver>` 가 자동 fetch.
|
||||
- install step 단순화: matrix 분기에서 EXTRAS 변수로 `[dev]` vs `[py313,dev]` 선택 후 단일 `uv pip install`.
|
||||
- 모든 `run:` 에 `shell: bash` 명시 (Gitea act-runner 호환).
|
||||
- **`pyproject.toml`**:
|
||||
- `scipy==1.13.1` → `scipy>=1.13,<2`.
|
||||
- `pyproj==3.6.1` → `pyproj>=3.6,<4`.
|
||||
- `numpy==2.0.2` → `numpy>=2.0.2,<3`.
|
||||
- `requires-python = ">=3.9"` → `">=3.11"` (CI matrix Py3.11/3.13 와 일치, Py3.9/3.10 legacy 종료).
|
||||
- `[tool.uv] no-progress = false` 제거.
|
||||
- **`uv.lock` 신규** (438 KB, 89 packages 해결): 다른 머신/CI에서 동일 환경 재현. `uv sync --frozen` 또는 `uv pip install -e ".[dev]" --frozen` 으로 lock 기준 install.
|
||||
|
||||
검증 (로컬): `uv lock` 성공 89 packages 해결, `ruff check` All checks passed.
|
||||
|
||||
### [feat] UI 진행률 인디케이터 + 로그 패널 축소 (#4 부분)
|
||||
|
||||
- **사용자 피드백 #4**: "느리게 느껴짐" → 긴 작업 중 시각적 피드백 부재.
|
||||
- **신규 위젯**: `self.progress_bar = ctk.CTkProgressBar(self.status_bar, mode="indeterminate", width=180, height=10, progress_color="#FF5F00")`. 기본 hidden (pack 안 함). MC overlap orange 색.
|
||||
- **신규 메서드** (`scanvas_maker.py` `SCanvasApp` 안):
|
||||
- `start_progress(label: str | None = None)`: progress_bar pack(side="right") + indeterminate animation 시작 + 옵션 status_text 갱신. `self.after(0, ...)` 로 메인 thread 안전.
|
||||
- `stop_progress(final_label: str | None = None)`: animation 정지 + pack_forget + status_text 옵션 갱신.
|
||||
- **로그 패널 축소**: `self.textbox` height 120 → 80. 인라인 로그 비중 줄여 캔버스 영역 확보. 사용자 피드백 "로그는 백엔드로" 의 점진적 적용 — 완전 제거가 아니라 디스크 (`%LOCALAPPDATA%\\S-CANVAS\\scanvas_harness.log` + `logs/scanvas.log`)가 주 기록처임을 주석으로 명시. 다음 라운드에서 toggle 버튼 또는 완전 제거.
|
||||
- **잔여 (#4 next round)**:
|
||||
- `start_progress`/`stop_progress` 를 실제 핫스팟 호출지에 wire (capture pipeline, 위성 타일, TIN densify 등).
|
||||
- 메인 thread 블로킹 작업을 worker thread 로 분리 — 그래야 progress animation 실제 동작.
|
||||
- 12개 `CTkToplevel` 인스펙터 패널 통합 (별도 multi-session).
|
||||
|
||||
### [chore] `harness/perf.py` ruff 정리
|
||||
|
||||
- `Optional[Callable[...]]` → `Callable[...] | None` (UP045, Py3.11+ native union).
|
||||
- `try: ...; except Exception: pass` → `with contextlib.suppress(Exception):` (SIM105).
|
||||
- 사용 안 되는 `# noqa: BLE001` 제거 (RUF100).
|
||||
- 결과: ruff `--no-cache` All checks passed.
|
||||
|
||||
---
|
||||
|
||||
## 2026-05-08 (후속 — UI 1차)
|
||||
|
||||
### [feat] Mastercard 팔레트 1차 적용 + 인트로 비디오 제거 (#4 부분)
|
||||
|
||||
@@ -19,13 +19,13 @@ CPU 이용률이 대폭 증가하는 프로세스를 ms 단위로 추적해서
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import contextlib
|
||||
import logging
|
||||
import time
|
||||
from collections.abc import Callable
|
||||
from contextlib import contextmanager
|
||||
from typing import Optional
|
||||
|
||||
_log_callable: Optional[Callable[[str], None]] = None
|
||||
_log_callable: Callable[[str], None] | None = None
|
||||
_logger = logging.getLogger("scanvas.perf")
|
||||
|
||||
|
||||
@@ -38,10 +38,9 @@ def set_perf_log(fn: Callable[[str], None] | None) -> None:
|
||||
def _emit(line: str) -> None:
|
||||
_logger.info(line)
|
||||
if _log_callable is not None:
|
||||
try:
|
||||
# 로그 sink 실패가 측정 흐름을 끊으면 안 됨 — 폭넓게 suppress.
|
||||
with contextlib.suppress(Exception):
|
||||
_log_callable(line)
|
||||
except Exception: # noqa: BLE001 (로그 sink 실패가 측정 흐름을 끊으면 안 됨)
|
||||
pass
|
||||
|
||||
|
||||
@contextmanager
|
||||
|
||||
@@ -16,7 +16,9 @@ name = "scanvas"
|
||||
version = "0.7.0"
|
||||
description = "S-CANVAS — Generative Design & Visualization Engine (DXF + DEM + AI)"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.9"
|
||||
# pyproj>=3.7 (py313 extras) 이 Py3.11+ 만 지원. CI matrix Py3.11/3.13 와 일치.
|
||||
# Py3.9/3.10 legacy 지원이 필요하면 pyproj 범위 좁혀야 함.
|
||||
requires-python = ">=3.11"
|
||||
license = { text = "Proprietary" }
|
||||
authors = [
|
||||
{ name = "Saman Corp.", email = "saman@example.com" },
|
||||
@@ -35,12 +37,12 @@ dependencies = [
|
||||
|
||||
# --- Geospatial / DXF ---
|
||||
"ezdxf==1.4.2",
|
||||
"pyproj==3.6.1",
|
||||
"pyproj>=3.6,<4", # 3.6.1 (build pin) ~ 3.7+ (py313 extras) 동시 수용. lock 파일이 정확 핀.
|
||||
"rasterio==1.4.3",
|
||||
|
||||
# --- Numerical ---
|
||||
"numpy==2.0.2",
|
||||
"scipy==1.13.1",
|
||||
"numpy>=2.0.2,<3", # py313 extras 와 충돌 방지 위해 범위 핀.
|
||||
"scipy>=1.13,<2", # 1.13.x (Py3.9~3.12) ~ 1.14+ (Py3.13) 둘 다 lock 가능.
|
||||
"matplotlib==3.9.4",
|
||||
|
||||
# --- Image / video ---
|
||||
@@ -99,9 +101,6 @@ Repository = "https://gitea.hmac.kr/HYUNJUNGLEE/scanvas.git"
|
||||
# Python 인터프리터 선택 우선순위 (uv가 자동 검색).
|
||||
python-preference = "managed" # managed = uv가 직접 받아 관리 (3.13 자동 다운로드 가능)
|
||||
|
||||
# 색상/진행률 표시.
|
||||
no-progress = false
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────────────
|
||||
# 빌드 시스템 (편집 가능 설치 / pip install -e . 가능)
|
||||
# ─────────────────────────────────────────────────────────────────────────
|
||||
|
||||
@@ -620,8 +620,10 @@ class SCanvasApp(ctk.CTk):
|
||||
self.map_view.set_zoom(6)
|
||||
self.map_view.set_position(36.5, 127.5)
|
||||
|
||||
# 2. 로그 (하단 — 스크롤 가능, 높이 줄임)
|
||||
self.textbox = ctk.CTkTextbox(self.main_frame, height=120, font=ctk.CTkFont(family="Consolas", size=12), border_width=1)
|
||||
# 2. 로그 (하단 — 스크롤 가능. 피드백 #4: 인라인 로그 비중 축소, 백엔드 파일이
|
||||
# 주 기록처. height 120 → 80 으로 캔버스 영역 확보.
|
||||
# 파일 로그: %LOCALAPPDATA%\\S-CANVAS\\scanvas_harness.log + logs/scanvas.log)
|
||||
self.textbox = ctk.CTkTextbox(self.main_frame, height=80, font=ctk.CTkFont(family="Consolas", size=12), border_width=1)
|
||||
self.textbox.grid(row=1, column=0, padx=0, pady=0, sticky="nsew")
|
||||
|
||||
# 3. 하단 상태 바
|
||||
@@ -634,6 +636,16 @@ class SCanvasApp(ctk.CTk):
|
||||
self.status_text = ctk.CTkLabel(self.status_bar, text="지형 데이터를 로드해 주세요.", font=ctk.CTkFont(size=12))
|
||||
self.status_text.pack(side="left")
|
||||
|
||||
# 진행률 인디케이터 (피드백 #4 — "느리게 느껴짐" 일부 해결).
|
||||
# 기본 hidden. start_progress/stop_progress 로 토글. indeterminate animation
|
||||
# 으로 "시스템이 살아있다" 시그널 — 실 진행률 측정은 future work (#11 perf 와 연계).
|
||||
# MC accent 색상 (#FF5F00 overlap orange) 적용.
|
||||
self.progress_bar = ctk.CTkProgressBar(
|
||||
self.status_bar, mode="indeterminate", width=180, height=10,
|
||||
progress_color="#FF5F00", fg_color=("#E0E0E0", "#333333"),
|
||||
)
|
||||
# 초기엔 hidden (pack 안 함). start_progress 시 등장.
|
||||
|
||||
self.log("S-CANVAS Generative Design Engine 구동 완료.")
|
||||
|
||||
# Perf 측정 라인을 GUI 로그에도 함께 표시 (#11). harness/perf.py 폴백 import 시
|
||||
@@ -741,6 +753,33 @@ class SCanvasApp(ctk.CTk):
|
||||
self.textbox.see("end")
|
||||
self.after(0, _update)
|
||||
|
||||
def start_progress(self, label: str | None = None) -> None:
|
||||
"""진행률 인디케이터 표시 + indeterminate animation 시작.
|
||||
|
||||
피드백 #4 — 긴 작업 시 "시스템 살아있음" 시그널. label 주면 status_text 도
|
||||
함께 갱신. 메인 thread 블로킹 작업이라도 호출 직전/직후에 표시 가능 (실
|
||||
애니메이션은 idle time 에 의존).
|
||||
"""
|
||||
def _start():
|
||||
with contextlib.suppress(Exception):
|
||||
self.progress_bar.pack(side="right", padx=(8, 12), pady=4)
|
||||
self.progress_bar.start()
|
||||
if label is not None:
|
||||
self.status_text.configure(text=label)
|
||||
self.update_idletasks()
|
||||
self.after(0, _start)
|
||||
|
||||
def stop_progress(self, final_label: str | None = None) -> None:
|
||||
"""진행률 인디케이터 숨김 + animation 정지."""
|
||||
def _stop():
|
||||
with contextlib.suppress(Exception):
|
||||
self.progress_bar.stop()
|
||||
self.progress_bar.pack_forget()
|
||||
if final_label is not None:
|
||||
self.status_text.configure(text=final_label)
|
||||
self.update_idletasks()
|
||||
self.after(0, _stop)
|
||||
|
||||
def _diag(self, message, *, reset=False):
|
||||
"""구조물 분류/추출 진단 로그 (scanvas_diagnostic.log).
|
||||
|
||||
|
||||
Reference in New Issue
Block a user