🌐 English|한국어

개발자 가이드

이 가이드는 PhyloForester에 기여하거나 기능을 확장하려는 개발자를 위한 문서예요.

아키텍처 개요

PhyloForester는 계층화된 아키텍처를 따라요:

┌─────────────────────────────┐
│   PhyloForester.py          │  Main Application
│   (Qt Main Window)          │
└──────────────┬──────────────┘
               │
┌──────────────┴──────────────┐
│   PfDialog.py               │  Dialog Layer
│   (UI Components)           │
└──────────────┬──────────────┘
               │
┌──────────────┴──────────────┐
│   PfModel.py                │  Data Model Layer
│   (Peewee ORM)              │
└──────────────┬──────────────┘
               │
┌──────────────┴──────────────┐
│   PfUtils.py                │  Utility Layer
│   (Helpers, Parsers)        │
└─────────────────────────────┘

핵심 컴포넌트

PhyloForester.py (메인 애플리케이션)

  • PhyloForesterMainWindow: 메인 윈도우 클래스

  • 트리 뷰 관리

  • 시그널/슬롯 연결

  • 메뉴 및 툴바 설정

PfModel.py (데이터베이스 모델)

  • PfProject: 프로젝트 모델

  • PfDatamatrix: 데이터매트릭스 모델

  • PfAnalysis: 분석 모델

  • PfTree: 트리 모델

  • PfPackage: 외부 소프트웨어 메타데이터

PfDialog.py (다이얼로그)

  • ProjectDialog: 프로젝트 속성

  • DatamatrixDialog: 데이터매트릭스 에디터

  • AnalysisDialog: 분석 설정

  • AnalysisViewer: 결과 뷰어

  • TreeViewer: 트리 시각화

PfUtils.py (유틸리티)

  • PhyloDatafile: 데이터 가져오기/내보내기

  • PhyloTreefile: 트리 파싱

  • 파일 형식 파서 (Nexus, Phylip, TNT)

  • 조상 상태 복원을 위한 Fitch 알고리즘

개발 환경 설정

사전 요구사항

  • Python 3.9+

  • Git

  • Qt5 개발 라이브러리 (PyQt5용)

저장소 복제

git clone https://github.com/jikhanjung/PhyloForester.git
cd PhyloForester

가상 환경 생성

python -m venv venv

# Windows
venv\\Scripts\\activate

# macOS/Linux
source venv/bin/activate

의존성 설치

# Runtime dependencies
pip install -r requirements.txt

# Development dependencies
pip install -r requirements-ci.txt

소스에서 실행

python PhyloForester.py

코드 구조

데이터 저장소

런타임 상태는 self.data_storage 딕셔너리에 저장돼요:

data_storage = {
    'project': {
        <project_id>: {
            'object': <PfProject instance>,
            'widget': <QWidget>,
            'tree_item': <QStandardItem>,
            'datamatrix': {}  # nested datamatrices
        }
    },
    'datamatrix': {
        <datamatrix_id>: {
            'object': <PfDatamatrix instance>,
            'widget': <QWidget>,
            'tree_item': <QStandardItem>,
            'analysis': {}  # nested analyses
        }
    },
    'analysis': {
        <analysis_id>: {
            'object': <PfAnalysis instance>,
            'widget': <QWidget>,
            'tree_item': <QStandardItem>
        }
    }
}

이를 통해 중복된 데이터베이스 쿼리를 방지하고 UI 일관성을 유지해요.

데이터베이스 스키마

class PfProject(BaseModel):
    name = CharField()
    description = TextField(null=True)

class PfDatamatrix(BaseModel):
    project = ForeignKeyField(PfProject, backref='datamatrices')
    name = CharField()
    datamatrix_json = TextField()  # JSON serialized matrix
    taxa_list_json = TextField()   # JSON serialized taxa names
    character_list_json = TextField()  # JSON serialized characters

class PfAnalysis(BaseModel):
    datamatrix = ForeignKeyField(PfDatamatrix, backref='analyses')
    name = CharField()
    analysis_type = CharField()  # 'Parsimony', 'ML', 'Bayesian'
    status = CharField()  # 'READY', 'RUNNING', 'COMPLETED', etc.
    parameters_json = TextField()

class PfTree(BaseModel):
    analysis = ForeignKeyField(PfAnalysis, backref='trees')
    tree_newick = TextField()
    tree_options_json = TextField()

테스트 실행

PhyloForester는 테스트에 pytest를 사용해요.

모든 테스트 실행

pytest tests/ -v

특정 테스트 파일 실행

pytest tests/test_utils.py -v

커버리지와 함께 실행

pytest tests/ --cov=. --cov-report=html

커버리지 보고서 보기: htmlcov/index.html

테스트 카테고리

테스트는 카테고리별로 마크되어 있어요:

  • @pytest.mark.unit: 유닛 테스트

  • @pytest.mark.model: 데이터베이스/모델 테스트

  • @pytest.mark.dialog: UI/다이얼로그 테스트

특정 카테고리 실행:

pytest -m unit

코드 품질

린팅

PhyloForester는 린팅에 Ruff를 사용해요:

ruff check .

자동 수정:

ruff check . --fix

코드 스타일

  • PEP 8 가이드라인을 따라요

  • 의미 있는 변수명을 사용해요

  • 공개 함수/클래스에 docstring을 추가해요

  • 함수를 집중되고 짧게 유지해요

타입 힌트

실용적인 곳에 타입 힌트를 사용해요:

def parse_nexus_file(filepath: str) -> Dict[str, Any]:
    """Parse a Nexus format file.

    Args:
        filepath: Path to Nexus file

    Returns:
        Dictionary with parsed data
    """
    pass

기여하기

워크플로우

  1. 저장소를 포크해요

  2. 기능 브랜치를 생성해요: git checkout -b feature/my-feature

  3. 변경사항을 만들고 커밋해요: git commit -m "Add my feature"

  4. 브랜치에 푸시해요: git push origin feature/my-feature

  5. GitHub에서 풀 리퀘스트를 생성해요

커밋 메시지

컨벤셔널 커밋을 따라요:

  • feat:: 새로운 기능

  • fix:: 버그 수정

  • docs:: 문서 변경

  • refactor:: 코드 리팩토링

  • test:: 테스트 추가/변경

  • chore:: 유지보수 작업

예시:

feat: Add support for FASTA format import

- Implement FASTA parser in PfUtils
- Add FASTA to import dialog options
- Add tests for FASTA parsing

풀 리퀘스트 가이드라인

  • 풀 리퀘스트가 무엇을 하는지 설명해요

  • 관련된 이슈를 참조해요

  • 새로운 기능에 대한 테스트를 포함해요

  • 필요한 경우 문서를 업데이트해요

  • CI 테스트가 통과하는지 확인해요

문서 빌드

Sphinx를 설치해요:

pip install -r docs/requirements.txt

HTML 문서를 빌드해요:

cd docs
sphinx-build -b html . _build/html

보기: docs/_build/html/index.html

변경 시 자동 재빌드:

sphinx-autobuild docs docs/_build/html

실행 파일 빌드

PhyloForester는 독립 실행 파일을 빌드하기 위해 PyInstaller를 사용해요.

빌드 스크립트

build.py 스크립트를 사용해요:

python build.py

자동으로 다음을 수행해요:

  • 플랫폼을 감지해요

  • ``version.py``에서 버전을 읽어요

  • 모든 의존성을 번들링해요

  • ``dist/``에 실행 파일을 생성해요

수동 PyInstaller

또는 PyInstaller를 직접 사용해요:

pyinstaller PhyloForester.spec

플랫폼별 참고사항

Windows:

  • .exe 파일을 생성해요

  • 선택적으로 Inno Setup 설치 프로그램을 생성해요

  • 대상 시스템에 Visual C++ 재배포 패키지가 필요해요

macOS:

  • .app 번들을 생성해요

  • 배포를 위해 코드 서명이 필요할 수 있어요

  • DMG 이미지를 위해 ``create-dmg``를 사용해요

Linux:

  • 독립 실행 파일을 생성해요

  • Qt5 라이브러리를 함께 배포해야 할 수 있어요

  • 배포를 위해 AppImage를 고려해요

버전 관리

PhyloForester는 시맨틱 버저닝(semver)을 사용해요.

버전 업데이트

manage_version.py 스크립트를 사용해요:

# Increment patch (0.1.0 -> 0.1.1)
python manage_version.py patch

# Increment minor (0.1.0 -> 0.2.0)
python manage_version.py minor

# Increment major (0.1.0 -> 1.0.0)
python manage_version.py major

# Start pre-release (0.1.0 -> 0.2.0-alpha.1)
python manage_version.py preminor

스크립트는 다음을 수행해요:

  • ``version.py``를 업데이트해요

  • ``CHANGELOG.md``를 업데이트해요

  • git 커밋과 태그를 생성해요

  • 확인을 요청해요

릴리스 프로세스

  1. 버전 업데이트: python manage_version.py minor

  2. 릴리스 노트로 ``CHANGELOG.md``를 업데이트해요

  3. 변경사항을 커밋해요

  4. GitHub에 푸시해요: git push origin main

  5. 태그를 생성하고 푸시해요: git push origin v0.2.0

  6. GitHub Actions가 자동으로 빌드하고 릴리스해요

CI/CD 파이프라인

PhyloForester는 CI/CD에 GitHub Actions를 사용해요.

워크플로우

test.yml - 자동화된 테스트

  • 푸시/풀 리퀘스트 시 실행돼요

  • Python 3.9, 3.10, 3.11을 테스트해요

  • 코드 커버리지를 측정해요

  • 린터를 실행해요

build.yml - 빌드 아티팩트

  • main에 푸시 시 실행돼요

  • Windows/macOS/Linux를 빌드해요

  • 빌드 아티팩트를 업로드해요

  • build.py 스크립트를 사용해요

release.yml - 자동화된 릴리스

  • git 태그 (v*.*.*)에서 트리거돼요

  • 먼저 테스트를 실행해요

  • 모든 플랫폼을 빌드해요

  • GitHub 릴리스를 생성해요

  • 설치 프로그램/패키지를 업로드해요

수동 릴리스

GitHub Actions UI를 사용해요:

  1. Actions → Manual Release로 이동해요

  2. “Run workflow”를 클릭해요

  3. 버전 번호를 입력해요

  4. 사전 릴리스/초안 옵션을 선택해요

  5. “Run workflow”를 클릭해요

기능 추가

새로운 분석 유형 추가

  1. PfModel.py 업데이트:

    새로운 분석 유형 상수를 추가해요

  2. AnalysisDialog 업데이트:

    새로운 유형에 대한 설정 UI를 추가해요

  3. 러너 구현:

    ``startAnalysis()``에 실행 로직을 추가해요

  4. 파서 추가:

    ``PfUtils.py``에서 출력 파일을 파싱해요

  5. 테스트 업데이트:

    새로운 분석 유형에 대한 테스트를 추가해요

새로운 가져오기 형식 추가

  1. PfUtils.py 업데이트:

    class PhyloDatafile:
        def load_myformat(self, filepath):
            """Load MyFormat data file."""
            # Parse file
            # Return taxa_list, character_list, datamatrix
    
  2. 가져오기 다이얼로그 업데이트:

    파일 필터에 형식을 추가해요

  3. 테스트 추가:

    ``data/``에 테스트 파일을 생성하고 ``tests/test_utils.py``에 테스트를 추가해요

UI 확장

커스텀 위젯은 다음을 따라야 해요:

  • 적절한 Qt 위젯을 상속해요

  • 통신을 위해 시그널/슬롯을 사용해요

  • ``PfDialog.py``에 추가하거나 ``PhyloForester.py``에 인라인으로 추가해요

예시:

class CustomTableView(QTableView):
    cellChanged = pyqtSignal(int, int, str)

    def __init__(self, parent=None):
        super().__init__(parent)
        # Custom initialization

    def custom_method(self):
        # Custom functionality
        self.cellChanged.emit(row, col, value)

디버깅

로깅

PhyloForester는 Python의 logging 모듈을 사용해요:

import logging
logger = logging.getLogger(__name__)

logger.debug("Debug message")
logger.info("Info message")
logger.warning("Warning message")
logger.error("Error message")

로그는 ``PaleoBytes/PhyloForester/Logs/``에 저장돼요

PyQt 디버깅

Qt 경고를 활성화해요:

export QT_DEBUG_PLUGINS=1
python PhyloForester.py

데이터베이스 검사

SQLite 브라우저를 사용해요:

sqlite3 ~/PaleoBytes/PhyloForester/PhyloForester.db

또는 DB Browser for SQLite (GUI)를 사용해요

리소스

연락처

다음 단계

  • 사용자 대상 기능은 :doc:`user_guide`를 참조하세요

  • 일반적인 문제는 :doc:`troubleshooting`을 참조하세요

  • 버전 히스토리는 :doc:`changelog`를 참조하세요