pyside6-reviewer について
現代的な PySide6 および Qt 6.8+ アプリ向けのコードレビュー用スキルです。スレッド処理、シグナルとスロット、モデル、リソース管理、非同期処理、QML 連携を、詳細な資料と PR チェックリストで確認します。
主な機能
- 01Qt 6.8+ の互換性確認
- 02スレッドセーフ性のレビュー
- 03シグナルとスロットの検証
- 04モデル/ビューと QML の確認
- 05リソース管理と非同期処理のレビュー
- 06詳細資料と PR チェックリスト
活用シーン
- 01PySide6 のプルリクエストのレビュー
- 02スレッド間 GUI アクセスの問題検出
- 03シグナルとスロットのシグネチャ確認
- 04モデル/ビューまたは QML コードの評価
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ akiselev/ qt-llm-template --skill pyside6-reviewerインストール後、Claude Code で/pyside6-reviewerを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
anti-patterns.mdmodel-view.mdperformance.mdqml-integration.mdreview.pysignals-slots.mdthreading.mdwidgets.md詳細
PySide6 コードレビュー
最新の PySide6/Qt 6.8 以降のアプリケーション向けの専門的なコードレビューです。
レビュープロセス
- Qt のバージョンに関する前提を特定する — コードが Qt 6.8 以降を対象としていることを確認します(Qt5 との互換性はありません)。
- スレッドセーフ性を確認する — すべての GUI 操作がメインスレッド上で行われていることと、適切なワーカーパターンが使われていることを確認します。
- シグナル/スロットの使い方を検証する — 最新の接続構文と適切なシグネチャを確認します。
- Model/View の実装を評価する — ロールの使用法、データメソッドのパターン、インデックスの有効性を確認します。
- リソース管理をレビューする — 親子間の所有関係を確認し、リークを防ぎます。
- 非同期パターンを評価する — QThread、QtConcurrent、asyncio との統合を確認します。
- 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())
詳細なリファレンスファイル
- references/signals-slots.md — シグナル/スロットのパターン、接続タイプ、スレッドセーフなシグナル発行
- references/model-view.md — QAbstractItemModel、ロール、プロキシ、デリゲート
- references/threading.md — QThread、QtConcurrent、非同期パターン、スレッドプール
- references/widgets.md — ウィジェットのライフサイクル、レイアウト、スタイル、高 DPI
- references/qml-integration.md — QML/Python ブリッジ、プロパティ、型登録
- references/performance.md — 描画の最適化、モデルの効率化、遅延読み込み
- references/anti-patterns.md — 修正方法を含む包括的なアンチパターン一覧
レビューチェックリスト(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によるプロパティバインディングを使用する - プラットフォームの権限には新しい
QPermissionAPI を使用する
コメント
Markdown 対応