Skip to content

Commit a497f71

Browse files
committed
docs: README整備 - 制限事項セクションを簡潔化・構造化
- 制限事項を箇条書きから見出し構造(###)に変更し可読性を向上 - デコレーターのクロージャ問題セクションを削除(isinstance()問題と本質的に同じため冗長) - 各制限事項の説明を簡潔化(詳細すぎる例や説明を整理) - 助詞の修正(「単一パッケージ使用すること」→「単一パッケージを使用すること」) - パッケージ構造で__init__.pyを含む構造を推奨と明記 - 冗長な見出し「### pytest実行」を削除
1 parent b3d2954 commit a497f71

1 file changed

Lines changed: 64 additions & 77 deletions

File tree

README.md

Lines changed: 64 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,6 @@ deep_reload(your_module)
7272

7373
このプロジェクトのテストはpytest専用です。開発環境でpytestを使用してテストを実行してください。
7474

75-
### pytest実行
76-
7775
```shell
7876
# リポジトリルートに移動(例)
7977
cd ~/Documents/maya/scripts/deep_reloader
@@ -101,81 +99,70 @@ pytest tests/ -q
10199

102100
## 制限事項・既知の問題
103101

104-
- **isinstance()チェックの失敗**(Python言語仕様の制約 - 解決不可能)
105-
- リロード前に作成したインスタンスは、リロード後のクラスで`isinstance()`チェックが失敗します
106-
- これはPython言語仕様の制約であり、すべてのリロードシステムが抱える共通の問題です
107-
- **原因**: リロード後、クラスオブジェクトのIDが変わるため、リロード前のインスタンスは古いクラスを参照し続けます
108-
- ****:
109-
```python
110-
# リロード前
111-
obj = MyClass()
112-
isinstance(obj, MyClass) # True
113-
114-
# deep_reload後
115-
isinstance(obj, MyClass) # False(objは古いMyClassのインスタンス、MyClassは新しいクラス)
116-
```
117-
- **回避策**:
118-
- リロード後にインスタンスを再作成する
119-
- クラス名での文字列比較を使用する(`type(obj).__name__ == 'MyClass'`
120-
- アプリケーションを再起動する
121-
122-
- **デコレーターのクロージャ問題**(Python言語仕様の制約 - 解決不可能)
123-
- デコレーター内で例外クラスをキャッチする場合、リロード後に正しくキャッチできません
124-
- これはPython言語仕様の制約であり、すべてのリロードシステム(`importlib.reload()`, IPythonの`%autoreload`等)が抱える共通の問題です
125-
- **原因**: デコレーターのクロージャは定義時にクラスオブジェクトへの参照を保持し、リロード後も古いクラスオブジェクトを参照し続けます
126-
- ****:
127-
```python
128-
# custom_error.py
129-
class CustomError(Exception):
130-
@staticmethod
131-
def catch(function):
132-
@functools.wraps(function)
133-
def wrapper(*args, **kwargs):
134-
try:
135-
return function(*args, **kwargs)
136-
except CustomError as e: # ←デコレーター定義時のCustomErrorを保持
137-
return f"Caught: {e}"
138-
return wrapper
139-
140-
# main.py
141-
@CustomError.catch # ←リロード後、このクロージャは古いCustomErrorを参照
142-
def risky_function():
143-
raise CustomError("Error") # ←新しいCustomErrorを投げる
144-
```
145-
- **回避策**:
146-
- デコレーターを使用せず、直接`try-except`で例外をキャッチする
147-
- 例外クラスをリロード対象から除外する
148-
- アプリケーションを再起動する
149-
150-
- **import文非対応**(仕様)
151-
- `import xxx.yyy` 形式の依存関係は対応していません
152-
- **理由**: `import xxx.yyy`はPythonのimport機構が親モジュール(`xxx`)に自動的に属性(`yyy`)を追加しますが、リロード時にこの属性が失われます。復元するには親モジュールへの属性追加を追跡し、リロード時に手動で復元する複雑な処理が必要で、`from xxx import yyy`よりもはるかに複雑になるため、対応を見送っています
153-
- **対応しているのはfrom-import形式のみです**:
154-
- `from xxx import yyy` 形式
155-
- `from .xxx import yyy` 形式
156-
- `from . import yyy` 形式
157-
- **推奨**: from-import を使用してください(例: `from deep_reloader import deep_reload`
158-
159-
- **単一パッケージのみリロード**(仕様)
160-
- `deep_reload()`は、指定されたモジュールと同じパッケージに属するモジュールのみをリロードします
161-
- **理由**: 組み込みモジュール(`sys`等)やサードパーティライブラリ(`maya.cmds`, `PySide2`等)のリロードを防ぎ、システムの安定性を保つため
162-
- ****: `deep_reload(myutils)` を実行すると、`myutils`パッケージ内のモジュールのみがリロードされます
163-
- **複数の自作パッケージを開発している場合**:
164-
```python
165-
# myutils と myfunctions の両方を開発中の場合
166-
deep_reload(myutils.helper) # myutilsパッケージをリロード
167-
deep_reload(myfunctions.main) # myfunctionsパッケージをリロード
168-
```
169-
170-
- **パッケージ構造が必須**(仕様)
171-
- `deep_reload()`はパッケージ化されたモジュールのみをサポートします
172-
- **理由**: 単体モジュール(`__init__.py`なし)では、標準ライブラリとユーザーコードの区別ができず、システムモジュールを誤ってリロードする危険性があるため
173-
- **非対応**: 単体の`.py`ファイル(例: `~/maya/scripts/my_tool.py`
174-
- **対応**: パッケージ化されたモジュール(例: `~/maya/scripts/my_project/__init__.py`
175-
- **単体モジュールの場合**: 標準の`importlib.reload()`を使用してください
176-
- **複数モジュールを使用する場合**: パッケージ化してください(`__init__.py`を含むディレクトリ構造)
177-
178-
### リリース状況
102+
### isinstance()の失敗(Python言語仕様の制約)
103+
104+
リロード前に作成したインスタンスは、リロード後のクラスで`isinstance()`が失敗します。これはPython言語仕様の制約であり、すべてのリロードシステムが抱える共通の問題です。
105+
106+
**原因**: リロード後、クラスオブジェクトのIDが変わるため。
107+
108+
****:
109+
```python
110+
# リロード前
111+
my_class = MyClass()
112+
isinstance(my_class, MyClass) # True
113+
114+
deep_reload(MyClass) # リロード
115+
116+
isinstance(my_class, MyClass) # False(my_classは古いMyClassのインスタンス、MyClassは新しいクラス)
117+
```
118+
119+
**回避策**:
120+
- リロード後にインスタンスを再作成する
121+
- クラス名での文字列比較を使用する(`type(my_class).__name__ == 'MyClass'`
122+
- Mayaを再起動する
123+
124+
### import文非対応(仕様)
125+
126+
`import xxx` 形式の依存関係は対応していません。
127+
128+
**理由**: リロード時に親モジュールへ自動追加された属性を復元する処理が複雑になるため。
129+
130+
**対応形式**: from-import形式のみ
131+
- `from xxx import yyy` 形式
132+
- `from .xxx import yyy` 形式
133+
- `from . import yyy` 形式
134+
135+
### 単一パッケージのみリロード(仕様)
136+
137+
`deep_reload()`は、渡されたモジュールと同じパッケージに属するモジュールのみをリロードします。
138+
139+
**理由**: 組み込みモジュール(`sys`等)やサードパーティライブラリ(`maya.cmds`, `PySide2`等)のリロードを防ぎ、システムの安定性を保つため。
140+
141+
****: `deep_reload(myutils)` を実行すると、`myutils`が属するパッケージのモジュールがリロード対象になります。
142+
143+
**複数の自作パッケージを開発している場合**:
144+
パッケージ間に依存関係がある場合、正常にリロードできない可能性があります。基本的には単一パッケージを使用することを推奨します。
145+
どうしても必要な場合は、依存関係の順序を考慮して複数回`deep_reload()`を呼び出してください。
146+
```python
147+
# 複数のパッケージでリロードしたい場合(非推奨)
148+
deep_reload(myutils)
149+
deep_reload(mytools)
150+
```
151+
152+
### パッケージ構造が必須(仕様)
153+
154+
`deep_reload()`はパッケージ化されたモジュールのみをサポートします。
155+
156+
**理由**: 単体モジュールでは、標準ライブラリとユーザーコードの区別ができず、システムモジュールを誤ってリロードする危険性があるため。
157+
158+
**非対応**: 単体の`.py`ファイル(例: `~/maya/scripts/my_tool.py`
159+
160+
**単体モジュールの場合**: 標準の`importlib.reload()`を使用してください。
161+
162+
**複数モジュールを使用する場合**: パッケージ化してください(`__init__.py`を含むディレクトリ構造を推奨)。
163+
164+
## リリース状況
165+
179166
- ✅ コア機能実装完了(from-import対応)
180167
- ✅ テストスイート
181168
- ✅ ドキュメント整備

0 commit comments

Comments
 (0)