mcpField
P
pyside6-reviewer

pyside6-reviewer

github.com/akiselevテスト・品質4214 回インストール39 週間前に更新
リポジトリ

pyside6-reviewer について

現代的な PySide6 および Qt 6.8+ アプリ向けのコードレビュー用スキルです。スレッド処理、シグナルとスロット、モデル、リソース管理、非同期処理、QML 連携を、詳細な資料と PR チェックリストで確認します。

主な機能

  1. 01Qt 6.8+ の互換性確認
  2. 02スレッドセーフ性のレビュー
  3. 03シグナルとスロットの検証
  4. 04モデル/ビューと QML の確認
  5. 05リソース管理と非同期処理のレビュー
  6. 06詳細資料と PR チェックリスト

活用シーン

  1. 01PySide6 のプルリクエストのレビュー
  2. 02スレッド間 GUI アクセスの問題検出
  3. 03シグナルとスロットのシグネチャ確認
  4. 04モデル/ビューまたは QML コードの評価

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/akiselev/qt-llm-template --skill pyside6-reviewer

インストール後、Claude Code で/pyside6-reviewerを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

anti-patterns.md
model-view.md
performance.md
qml-integration.md
review.py
signals-slots.md
threading.md
widgets.md

詳細

PySide6 コードレビュー

最新の PySide6/Qt 6.8 以降のアプリケーション向けの専門的なコードレビューです。

レビュープロセス

  1. Qt のバージョンに関する前提を特定する — コードが Qt 6.8 以降を対象としていることを確認します(Qt5 との互換性はありません)。
  2. スレッドセーフ性を確認する — すべての GUI 操作がメインスレッド上で行われていることと、適切なワーカーパターンが使われていることを確認します。
  3. シグナル/スロットの使い方を検証する — 最新の接続構文と適切なシグネチャを確認します。
  4. Model/View の実装を評価する — ロールの使用法、データメソッドのパターン、インデックスの有効性を確認します。
  5. リソース管理をレビューする — 親子間の所有関係を確認し、リークを防ぎます。
  6. 非同期パターンを評価する — QThread、QtConcurrent、asyncio との統合を確認します。
  7. QML 統合を確認する — プロパティのバインディング、型登録、コンテキストの公開を確認します。

重大なアンチパターン(必ず指摘する)

# WRONG: GUI operation from worker thread
class Worker(QThread):
    def run(self):
        self.label.setText("Done")  # CRASH: Cross-thread GUI access

# WRONG: Blocking the event loop
def on_button_click(self):
    time.sleep(5)  # FREEZES UI
    requests.get(url)  # FREEZES UI

# WRONG: Old-style signal connection (Qt4/5 legacy)
self.connect(button, SIGNAL("clicked()"), self.handler)

# WRONG: String-based slot connection
button.clicked.connect("self.handler")  # Should be callable

# WRONG: No parent = memory leak risk
label = QLabel("text")  # Should have parent or be assigned to layout

# WRONG: Deleting QObject while signals pending
obj.deleteLater()  # OK
del obj  # WRONG if signals/slots active

# WRONG: Direct widget manipulation in QThread.run()
class BadWorker(QThread):
    def run(self):
        self.progress_bar.setValue(50)  # Thread violation!

最新のパターン(必須)

シグナル/スロット接続
# Qt 6 style - always use this
button.clicked.connect(self.on_click)
button.clicked.connect(lambda: self.handler(arg))

# Typed signals with modern syntax
class Worker(QObject):
    progress = Signal(int)          # Single type
    result = Signal(str, list)      # Multiple types
    error = Signal(Exception)       # Exception passing
    finished = Signal()             # No arguments
スレッドセーフなワーカーパターン
class Worker(QObject):
    finished = Signal()
    progress = Signal(int)
    result = Signal(object)
    error = Signal(str)

    @Slot()
    def run(self):
        try:
            for i in range(100):
                # Do work
                self.progress.emit(i)
            self.result.emit(data)
        except Exception as e:
            self.error.emit(str(e))
        finally:
            self.finished.emit()

# Usage
thread = QThread()
worker = Worker()
worker.moveToThread(thread)
thread.started.connect(worker.run)
worker.finished.connect(thread.quit)
worker.finished.connect(worker.deleteLater)
thread.finished.connect(thread.deleteLater)
thread.start()
非同期統合(Qt 6.8 以降)
import asyncio
from PySide6.QtAsyncio import QAsyncioEventLoopPolicy

# Set up asyncio with Qt event loop
asyncio.set_event_loop_policy(QAsyncioEventLoopPolicy())

class AsyncWidget(QWidget):
    async def fetch_data(self):
        async with aiohttp.ClientSession() as session:
            async with session.get(url) as response:
                return await response.json()
    
    def start_fetch(self):
        asyncio.ensure_future(self.fetch_data())

詳細なリファレンスファイル

レビューチェックリスト(PR で使用)

スレッドセーフ性
  • ウィジェット/GUI の呼び出しはすべてメインスレッド上でのみ行う
  • ワーカーは UI の更新にシグナル/スロットを使用する
  • メインスレッドで time.sleep() やブロッキング呼び出しを使用しない
  • QThread のサブクラスでは run() のみをオーバーライドし、コンストラクターで処理を行わない
  • moveToThread() を正しく使用する(オブジェクトに親がない)
メモリ管理
  • ウィジェットには親を設定するか、レイアウトに追加する
  • QObject には deleteLater() を使用し、del は使用しない
  • ラムダ接続で古い参照をキャプチャしない
  • 循環するシグナル接続を避ける
  • モデルのデータは参照ではなく値で返す
シグナル/スロットの正確性
  • 最新の接続構文を使用する(文字列は使用しない)
  • シグナルのシグネチャとスロットのシグネチャを一致させる
  • すべてのスロットに @Slot() デコレーターを付ける
  • スレッド間のシグナルには Qt.QueuedConnection を使用する
  • シグナルはクラス属性として定義する
Model/View
  • 変更を beginInsertRows()/endInsertRows() で囲む
  • 更新時に dataChanged を発行する
  • アクセス前に index.isValid() を確認する
  • カスタムロールには Qt.UserRole + n を使用する
  • QML との互換性のために roleNames() をオーバーライドする
パフォーマンス
  • ペイントイベント内でウィジェットを作成しない
  • 再描画には repaint() ではなく update() を使用する
  • 大きなリストには QAbstractItemModel を使用する(QListWidget は使用しない)
  • コストの高いデータには遅延読み込みを使用する
  • 一括更新中は blockSignals() を使用する
Qt 6.8 以降の特記事項
  • 新しい列挙型スコープを使用する(Qt.AlignmentFlag.AlignCenter)
  • 非同期パターンにはサードパーティ製ではなく QtAsyncio を使用する
  • 型登録には QML_ELEMENT マクロに相当する機能を使用する
  • 適切な場合は QProperty によるプロパティバインディングを使用する
  • プラットフォームの権限には新しい QPermission API を使用する

コメント