publishsub


Namepublishsub JSON
Version 1.0.0 PyPI version JSON
download
home_pagehttps://github.com/tikipiya/publishsub
Summary依存関係ゼロの軽量パブリッシュ/サブスクライブメッセージングライブラリ
upload_time2025-07-11 12:52:43
maintainerNone
docs_urlNone
authortikisan
requires_python>=3.7
licenseNone
keywords pubsub publish subscribe messaging event observer pertern
VCS
bugtrack_url
requirements pytest pytest-cov black flake8
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # publishsub

**Python用の依存関係ゼロ軽量パブリッシュ/サブスクライブメッセージングライブラリ**

ゲーム、GUIアプリケーション、並列処理通信に最適なシンプルで高速、依存関係のないpub/subライブラリです。

## 特徴

- 🚀 **依存関係ゼロ** - 外部ライブラリ不要
- 🧵 **スレッドセーフ** - マルチスレッドアプリケーションで安全に使用可能
- 🔄 **メモリ効率** - 弱参照を使用してメモリリークを防止
- 🎯 **シンプルAPI** - 最小限のセットアップで簡単に使用可能
- 🔍 **デバッグサポート** - 組み込みデバッグ機能
- 📦 **軽量** - 最小限のオーバーヘッドで高速パフォーマンス

## インストール

```bash
pip install publishsub
```

## クイックスタート

```python
import publishsub as pubsub

# イベントハンドラを定義
def on_player_join(data):
    print(f"プレイヤー {data['name']} がゲームに参加しました!")

def on_game_over(data):
    print(f"ゲーム終了!最終スコア: {data['score']}")

# イベントを購読
pubsub.subscribe("player_join", on_player_join)
pubsub.subscribe("game_over", on_game_over)

# イベントを発行
pubsub.publish("player_join", {"name": "Alice", "id": 123})
pubsub.publish("game_over", {"score": 9500, "winner": "Alice"})
```

## 高度な使用法

### クラスインスタンスの使用

```python
from publishsub import PubSub

# 独自のインスタンスを作成
ps = PubSub()

# 購読してサブスクリプションIDを取得
sub_id = ps.subscribe("my_event", lambda data: print(data))

# イベントを発行
ps.publish("my_event", "Hello World!")

# IDを使用して購読解除
ps.unsubscribe("my_event", sub_id)
```

### イベント管理

```python
import publishsub as pubsub

# 購読者数を確認
count = pubsub.subscribers_count("my_event")
print(f"イベントの購読者数: {count}")

# 購読者のいるすべてのイベントを一覧表示
events = pubsub.list_events()
print(f"アクティブなイベント: {events}")

# 特定のイベントの購読者をクリア
pubsub.clear("my_event")

# すべての購読者をクリア
pubsub.clear()
```

### デバッグモード

```python
import publishsub as pubsub

# デバッグログを有効にする
pubsub.enable_debug(True)

# すべての操作がログに記録される
pubsub.subscribe("debug_event", lambda x: print(x))
pubsub.publish("debug_event", "デバッグ情報が表示されます")
```

## 使用例

### ゲーム開発

```python
import publishsub as pubsub

# ゲームイベント
def on_enemy_spawn(enemy_data):
    print(f"敵が出現: {enemy_data['type']}")

def on_player_damage(damage_data):
    print(f"プレイヤーが {damage_data['amount']} ダメージを受けました")

# ゲームイベントを購読
pubsub.subscribe("enemy_spawn", on_enemy_spawn)
pubsub.subscribe("player_damage", on_player_damage)

# ゲームループ内で
pubsub.publish("enemy_spawn", {"type": "ゴブリン", "x": 100, "y": 200})
pubsub.publish("player_damage", {"amount": 25, "source": "ゴブリン"})
```

### GUIアプリケーション

```python
import publishsub as pubsub

# UIイベントハンドラ
def on_button_click(data):
    print(f"ボタン {data['button_id']} がクリックされました")

def on_window_resize(data):
    print(f"ウィンドウサイズが {data['width']}x{data['height']} に変更されました")

# UIイベントを購読
pubsub.subscribe("button_click", on_button_click)
pubsub.subscribe("window_resize", on_window_resize)

# UIコードで
pubsub.publish("button_click", {"button_id": "save_btn"})
pubsub.publish("window_resize", {"width": 800, "height": 600})
```

### 並列処理

```python
import publishsub as pubsub
import threading

# ワーカー間通信
def on_task_complete(data):
    print(f"タスク {data['task_id']} がワーカー {data['worker_id']} によって完了")

def on_error(data):
    print(f"タスク {data['task_id']} でエラー: {data['error']}")

# ワーカーイベントを購読
pubsub.subscribe("task_complete", on_task_complete)
pubsub.subscribe("error", on_error)

# ワーカースレッドで
def worker_thread(worker_id):
    # ... 作業を実行 ...
    pubsub.publish("task_complete", {"task_id": 123, "worker_id": worker_id})

# ワーカーを開始
for i in range(3):
    threading.Thread(target=worker_thread, args=(i,)).start()
```

## APIリファレンス

### 関数

#### `subscribe(event: str, callback: Callable) -> str`
コールバック関数でイベントを購読します。
- **event**: 購読するイベント名
- **callback**: イベントが発行されたときに呼び出される関数
- **戻り値**: 購読解除に使用するサブスクリプションID

#### `unsubscribe(event: str, subscription_id: str) -> bool`
サブスクリプションIDを使用してイベントの購読を解除します。
- **event**: イベント名
- **subscription_id**: subscribe()によって返されたサブスクリプションID
- **戻り値**: 購読解除に成功した場合True

#### `publish(event: str, data: Any = None) -> int`
オプションのデータでイベントを発行します。
- **event**: 発行するイベント名
- **data**: イベントと一緒に送信するオプションのデータ
- **戻り値**: イベントを受信した購読者数

#### `subscribers_count(event: str) -> int`
イベントのアクティブな購読者数を取得します。
- **event**: イベント名
- **戻り値**: アクティブな購読者数

#### `list_events() -> List[str]`
購読者のいるすべてのイベントのリストを取得します。
- **戻り値**: イベント名のリスト

#### `clear(event: Optional[str] = None) -> None`
イベントのすべての購読者をクリアします。イベントが指定されない場合はすべてクリアします。
- **event**: クリアする特定のイベント、またはすべてをクリアする場合はNone

#### `enable_debug(enable: bool = True) -> None`
デバッグログを有効または無効にします。
- **enable**: デバッグログを有効にする場合True、無効にする場合False

## スレッドセーフ

このライブラリは完全にスレッドセーフで、追加の同期なしにマルチスレッドアプリケーションで使用できます。

## メモリ管理

ライブラリはコールバックに弱参照を使用してメモリリークを防ぎます。購読されたメソッドを持つオブジェクトがガベージコレクションされると、それらの購読は自動的にクリーンアップされます。

## パフォーマンス

- **軽量**: 最小限のメモリフットプリント
- **高速**: 高頻度なイベント発行に最適化
- **スケーラブル**: 数千のイベントと購読者を効率的に処理

## ライセンス

MIT License - 詳細はLICENSEファイルをご覧ください。

## 貢献

貢献を歓迎します!プルリクエストをお気軽にお送りください。

## 作者

[tikipiya](https://github.com/tikipiya)が作成

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/tikipiya/publishsub",
    "name": "publishsub",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.7",
    "maintainer_email": null,
    "keywords": "pubsub, publish, subscribe, messaging, event, observer, pertern",
    "author": "tikisan",
    "author_email": "s2501082@sendai-nct.jp",
    "download_url": "https://files.pythonhosted.org/packages/34/52/d08ed36522b7467457ec0ded68dece0539a8a724ac04317c0469b1c58651/publishsub-1.0.0.tar.gz",
    "platform": null,
    "description": "# publishsub\r\n\r\n**Python\u7528\u306e\u4f9d\u5b58\u95a2\u4fc2\u30bc\u30ed\u8efd\u91cf\u30d1\u30d6\u30ea\u30c3\u30b7\u30e5/\u30b5\u30d6\u30b9\u30af\u30e9\u30a4\u30d6\u30e1\u30c3\u30bb\u30fc\u30b8\u30f3\u30b0\u30e9\u30a4\u30d6\u30e9\u30ea**\r\n\r\n\u30b2\u30fc\u30e0\u3001GUI\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3001\u4e26\u5217\u51e6\u7406\u901a\u4fe1\u306b\u6700\u9069\u306a\u30b7\u30f3\u30d7\u30eb\u3067\u9ad8\u901f\u3001\u4f9d\u5b58\u95a2\u4fc2\u306e\u306a\u3044pub/sub\u30e9\u30a4\u30d6\u30e9\u30ea\u3067\u3059\u3002\r\n\r\n## \u7279\u5fb4\r\n\r\n- \ud83d\ude80 **\u4f9d\u5b58\u95a2\u4fc2\u30bc\u30ed** - \u5916\u90e8\u30e9\u30a4\u30d6\u30e9\u30ea\u4e0d\u8981\r\n- \ud83e\uddf5 **\u30b9\u30ec\u30c3\u30c9\u30bb\u30fc\u30d5** - \u30de\u30eb\u30c1\u30b9\u30ec\u30c3\u30c9\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3067\u5b89\u5168\u306b\u4f7f\u7528\u53ef\u80fd\r\n- \ud83d\udd04 **\u30e1\u30e2\u30ea\u52b9\u7387** - \u5f31\u53c2\u7167\u3092\u4f7f\u7528\u3057\u3066\u30e1\u30e2\u30ea\u30ea\u30fc\u30af\u3092\u9632\u6b62\r\n- \ud83c\udfaf **\u30b7\u30f3\u30d7\u30ebAPI** - \u6700\u5c0f\u9650\u306e\u30bb\u30c3\u30c8\u30a2\u30c3\u30d7\u3067\u7c21\u5358\u306b\u4f7f\u7528\u53ef\u80fd\r\n- \ud83d\udd0d **\u30c7\u30d0\u30c3\u30b0\u30b5\u30dd\u30fc\u30c8** - \u7d44\u307f\u8fbc\u307f\u30c7\u30d0\u30c3\u30b0\u6a5f\u80fd\r\n- \ud83d\udce6 **\u8efd\u91cf** - \u6700\u5c0f\u9650\u306e\u30aa\u30fc\u30d0\u30fc\u30d8\u30c3\u30c9\u3067\u9ad8\u901f\u30d1\u30d5\u30a9\u30fc\u30de\u30f3\u30b9\r\n\r\n## \u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\r\n\r\n```bash\r\npip install publishsub\r\n```\r\n\r\n## \u30af\u30a4\u30c3\u30af\u30b9\u30bf\u30fc\u30c8\r\n\r\n```python\r\nimport publishsub as pubsub\r\n\r\n# \u30a4\u30d9\u30f3\u30c8\u30cf\u30f3\u30c9\u30e9\u3092\u5b9a\u7fa9\r\ndef on_player_join(data):\r\n    print(f\"\u30d7\u30ec\u30a4\u30e4\u30fc {data['name']} \u304c\u30b2\u30fc\u30e0\u306b\u53c2\u52a0\u3057\u307e\u3057\u305f\uff01\")\r\n\r\ndef on_game_over(data):\r\n    print(f\"\u30b2\u30fc\u30e0\u7d42\u4e86\uff01\u6700\u7d42\u30b9\u30b3\u30a2: {data['score']}\")\r\n\r\n# \u30a4\u30d9\u30f3\u30c8\u3092\u8cfc\u8aad\r\npubsub.subscribe(\"player_join\", on_player_join)\r\npubsub.subscribe(\"game_over\", on_game_over)\r\n\r\n# \u30a4\u30d9\u30f3\u30c8\u3092\u767a\u884c\r\npubsub.publish(\"player_join\", {\"name\": \"Alice\", \"id\": 123})\r\npubsub.publish(\"game_over\", {\"score\": 9500, \"winner\": \"Alice\"})\r\n```\r\n\r\n## \u9ad8\u5ea6\u306a\u4f7f\u7528\u6cd5\r\n\r\n### \u30af\u30e9\u30b9\u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u306e\u4f7f\u7528\r\n\r\n```python\r\nfrom publishsub import PubSub\r\n\r\n# \u72ec\u81ea\u306e\u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u3092\u4f5c\u6210\r\nps = PubSub()\r\n\r\n# \u8cfc\u8aad\u3057\u3066\u30b5\u30d6\u30b9\u30af\u30ea\u30d7\u30b7\u30e7\u30f3ID\u3092\u53d6\u5f97\r\nsub_id = ps.subscribe(\"my_event\", lambda data: print(data))\r\n\r\n# \u30a4\u30d9\u30f3\u30c8\u3092\u767a\u884c\r\nps.publish(\"my_event\", \"Hello World!\")\r\n\r\n# ID\u3092\u4f7f\u7528\u3057\u3066\u8cfc\u8aad\u89e3\u9664\r\nps.unsubscribe(\"my_event\", sub_id)\r\n```\r\n\r\n### \u30a4\u30d9\u30f3\u30c8\u7ba1\u7406\r\n\r\n```python\r\nimport publishsub as pubsub\r\n\r\n# \u8cfc\u8aad\u8005\u6570\u3092\u78ba\u8a8d\r\ncount = pubsub.subscribers_count(\"my_event\")\r\nprint(f\"\u30a4\u30d9\u30f3\u30c8\u306e\u8cfc\u8aad\u8005\u6570: {count}\")\r\n\r\n# \u8cfc\u8aad\u8005\u306e\u3044\u308b\u3059\u3079\u3066\u306e\u30a4\u30d9\u30f3\u30c8\u3092\u4e00\u89a7\u8868\u793a\r\nevents = pubsub.list_events()\r\nprint(f\"\u30a2\u30af\u30c6\u30a3\u30d6\u306a\u30a4\u30d9\u30f3\u30c8: {events}\")\r\n\r\n# \u7279\u5b9a\u306e\u30a4\u30d9\u30f3\u30c8\u306e\u8cfc\u8aad\u8005\u3092\u30af\u30ea\u30a2\r\npubsub.clear(\"my_event\")\r\n\r\n# \u3059\u3079\u3066\u306e\u8cfc\u8aad\u8005\u3092\u30af\u30ea\u30a2\r\npubsub.clear()\r\n```\r\n\r\n### \u30c7\u30d0\u30c3\u30b0\u30e2\u30fc\u30c9\r\n\r\n```python\r\nimport publishsub as pubsub\r\n\r\n# \u30c7\u30d0\u30c3\u30b0\u30ed\u30b0\u3092\u6709\u52b9\u306b\u3059\u308b\r\npubsub.enable_debug(True)\r\n\r\n# \u3059\u3079\u3066\u306e\u64cd\u4f5c\u304c\u30ed\u30b0\u306b\u8a18\u9332\u3055\u308c\u308b\r\npubsub.subscribe(\"debug_event\", lambda x: print(x))\r\npubsub.publish(\"debug_event\", \"\u30c7\u30d0\u30c3\u30b0\u60c5\u5831\u304c\u8868\u793a\u3055\u308c\u307e\u3059\")\r\n```\r\n\r\n## \u4f7f\u7528\u4f8b\r\n\r\n### \u30b2\u30fc\u30e0\u958b\u767a\r\n\r\n```python\r\nimport publishsub as pubsub\r\n\r\n# \u30b2\u30fc\u30e0\u30a4\u30d9\u30f3\u30c8\r\ndef on_enemy_spawn(enemy_data):\r\n    print(f\"\u6575\u304c\u51fa\u73fe: {enemy_data['type']}\")\r\n\r\ndef on_player_damage(damage_data):\r\n    print(f\"\u30d7\u30ec\u30a4\u30e4\u30fc\u304c {damage_data['amount']} \u30c0\u30e1\u30fc\u30b8\u3092\u53d7\u3051\u307e\u3057\u305f\")\r\n\r\n# \u30b2\u30fc\u30e0\u30a4\u30d9\u30f3\u30c8\u3092\u8cfc\u8aad\r\npubsub.subscribe(\"enemy_spawn\", on_enemy_spawn)\r\npubsub.subscribe(\"player_damage\", on_player_damage)\r\n\r\n# \u30b2\u30fc\u30e0\u30eb\u30fc\u30d7\u5185\u3067\r\npubsub.publish(\"enemy_spawn\", {\"type\": \"\u30b4\u30d6\u30ea\u30f3\", \"x\": 100, \"y\": 200})\r\npubsub.publish(\"player_damage\", {\"amount\": 25, \"source\": \"\u30b4\u30d6\u30ea\u30f3\"})\r\n```\r\n\r\n### GUI\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\r\n\r\n```python\r\nimport publishsub as pubsub\r\n\r\n# UI\u30a4\u30d9\u30f3\u30c8\u30cf\u30f3\u30c9\u30e9\r\ndef on_button_click(data):\r\n    print(f\"\u30dc\u30bf\u30f3 {data['button_id']} \u304c\u30af\u30ea\u30c3\u30af\u3055\u308c\u307e\u3057\u305f\")\r\n\r\ndef on_window_resize(data):\r\n    print(f\"\u30a6\u30a3\u30f3\u30c9\u30a6\u30b5\u30a4\u30ba\u304c {data['width']}x{data['height']} \u306b\u5909\u66f4\u3055\u308c\u307e\u3057\u305f\")\r\n\r\n# UI\u30a4\u30d9\u30f3\u30c8\u3092\u8cfc\u8aad\r\npubsub.subscribe(\"button_click\", on_button_click)\r\npubsub.subscribe(\"window_resize\", on_window_resize)\r\n\r\n# UI\u30b3\u30fc\u30c9\u3067\r\npubsub.publish(\"button_click\", {\"button_id\": \"save_btn\"})\r\npubsub.publish(\"window_resize\", {\"width\": 800, \"height\": 600})\r\n```\r\n\r\n### \u4e26\u5217\u51e6\u7406\r\n\r\n```python\r\nimport publishsub as pubsub\r\nimport threading\r\n\r\n# \u30ef\u30fc\u30ab\u30fc\u9593\u901a\u4fe1\r\ndef on_task_complete(data):\r\n    print(f\"\u30bf\u30b9\u30af {data['task_id']} \u304c\u30ef\u30fc\u30ab\u30fc {data['worker_id']} \u306b\u3088\u3063\u3066\u5b8c\u4e86\")\r\n\r\ndef on_error(data):\r\n    print(f\"\u30bf\u30b9\u30af {data['task_id']} \u3067\u30a8\u30e9\u30fc: {data['error']}\")\r\n\r\n# \u30ef\u30fc\u30ab\u30fc\u30a4\u30d9\u30f3\u30c8\u3092\u8cfc\u8aad\r\npubsub.subscribe(\"task_complete\", on_task_complete)\r\npubsub.subscribe(\"error\", on_error)\r\n\r\n# \u30ef\u30fc\u30ab\u30fc\u30b9\u30ec\u30c3\u30c9\u3067\r\ndef worker_thread(worker_id):\r\n    # ... \u4f5c\u696d\u3092\u5b9f\u884c ...\r\n    pubsub.publish(\"task_complete\", {\"task_id\": 123, \"worker_id\": worker_id})\r\n\r\n# \u30ef\u30fc\u30ab\u30fc\u3092\u958b\u59cb\r\nfor i in range(3):\r\n    threading.Thread(target=worker_thread, args=(i,)).start()\r\n```\r\n\r\n## API\u30ea\u30d5\u30a1\u30ec\u30f3\u30b9\r\n\r\n### \u95a2\u6570\r\n\r\n#### `subscribe(event: str, callback: Callable) -> str`\r\n\u30b3\u30fc\u30eb\u30d0\u30c3\u30af\u95a2\u6570\u3067\u30a4\u30d9\u30f3\u30c8\u3092\u8cfc\u8aad\u3057\u307e\u3059\u3002\r\n- **event**: \u8cfc\u8aad\u3059\u308b\u30a4\u30d9\u30f3\u30c8\u540d\r\n- **callback**: \u30a4\u30d9\u30f3\u30c8\u304c\u767a\u884c\u3055\u308c\u305f\u3068\u304d\u306b\u547c\u3073\u51fa\u3055\u308c\u308b\u95a2\u6570\r\n- **\u623b\u308a\u5024**: \u8cfc\u8aad\u89e3\u9664\u306b\u4f7f\u7528\u3059\u308b\u30b5\u30d6\u30b9\u30af\u30ea\u30d7\u30b7\u30e7\u30f3ID\r\n\r\n#### `unsubscribe(event: str, subscription_id: str) -> bool`\r\n\u30b5\u30d6\u30b9\u30af\u30ea\u30d7\u30b7\u30e7\u30f3ID\u3092\u4f7f\u7528\u3057\u3066\u30a4\u30d9\u30f3\u30c8\u306e\u8cfc\u8aad\u3092\u89e3\u9664\u3057\u307e\u3059\u3002\r\n- **event**: \u30a4\u30d9\u30f3\u30c8\u540d\r\n- **subscription_id**: subscribe()\u306b\u3088\u3063\u3066\u8fd4\u3055\u308c\u305f\u30b5\u30d6\u30b9\u30af\u30ea\u30d7\u30b7\u30e7\u30f3ID\r\n- **\u623b\u308a\u5024**: \u8cfc\u8aad\u89e3\u9664\u306b\u6210\u529f\u3057\u305f\u5834\u5408True\r\n\r\n#### `publish(event: str, data: Any = None) -> int`\r\n\u30aa\u30d7\u30b7\u30e7\u30f3\u306e\u30c7\u30fc\u30bf\u3067\u30a4\u30d9\u30f3\u30c8\u3092\u767a\u884c\u3057\u307e\u3059\u3002\r\n- **event**: \u767a\u884c\u3059\u308b\u30a4\u30d9\u30f3\u30c8\u540d\r\n- **data**: \u30a4\u30d9\u30f3\u30c8\u3068\u4e00\u7dd2\u306b\u9001\u4fe1\u3059\u308b\u30aa\u30d7\u30b7\u30e7\u30f3\u306e\u30c7\u30fc\u30bf\r\n- **\u623b\u308a\u5024**: \u30a4\u30d9\u30f3\u30c8\u3092\u53d7\u4fe1\u3057\u305f\u8cfc\u8aad\u8005\u6570\r\n\r\n#### `subscribers_count(event: str) -> int`\r\n\u30a4\u30d9\u30f3\u30c8\u306e\u30a2\u30af\u30c6\u30a3\u30d6\u306a\u8cfc\u8aad\u8005\u6570\u3092\u53d6\u5f97\u3057\u307e\u3059\u3002\r\n- **event**: \u30a4\u30d9\u30f3\u30c8\u540d\r\n- **\u623b\u308a\u5024**: \u30a2\u30af\u30c6\u30a3\u30d6\u306a\u8cfc\u8aad\u8005\u6570\r\n\r\n#### `list_events() -> List[str]`\r\n\u8cfc\u8aad\u8005\u306e\u3044\u308b\u3059\u3079\u3066\u306e\u30a4\u30d9\u30f3\u30c8\u306e\u30ea\u30b9\u30c8\u3092\u53d6\u5f97\u3057\u307e\u3059\u3002\r\n- **\u623b\u308a\u5024**: \u30a4\u30d9\u30f3\u30c8\u540d\u306e\u30ea\u30b9\u30c8\r\n\r\n#### `clear(event: Optional[str] = None) -> None`\r\n\u30a4\u30d9\u30f3\u30c8\u306e\u3059\u3079\u3066\u306e\u8cfc\u8aad\u8005\u3092\u30af\u30ea\u30a2\u3057\u307e\u3059\u3002\u30a4\u30d9\u30f3\u30c8\u304c\u6307\u5b9a\u3055\u308c\u306a\u3044\u5834\u5408\u306f\u3059\u3079\u3066\u30af\u30ea\u30a2\u3057\u307e\u3059\u3002\r\n- **event**: \u30af\u30ea\u30a2\u3059\u308b\u7279\u5b9a\u306e\u30a4\u30d9\u30f3\u30c8\u3001\u307e\u305f\u306f\u3059\u3079\u3066\u3092\u30af\u30ea\u30a2\u3059\u308b\u5834\u5408\u306fNone\r\n\r\n#### `enable_debug(enable: bool = True) -> None`\r\n\u30c7\u30d0\u30c3\u30b0\u30ed\u30b0\u3092\u6709\u52b9\u307e\u305f\u306f\u7121\u52b9\u306b\u3057\u307e\u3059\u3002\r\n- **enable**: \u30c7\u30d0\u30c3\u30b0\u30ed\u30b0\u3092\u6709\u52b9\u306b\u3059\u308b\u5834\u5408True\u3001\u7121\u52b9\u306b\u3059\u308b\u5834\u5408False\r\n\r\n## \u30b9\u30ec\u30c3\u30c9\u30bb\u30fc\u30d5\r\n\r\n\u3053\u306e\u30e9\u30a4\u30d6\u30e9\u30ea\u306f\u5b8c\u5168\u306b\u30b9\u30ec\u30c3\u30c9\u30bb\u30fc\u30d5\u3067\u3001\u8ffd\u52a0\u306e\u540c\u671f\u306a\u3057\u306b\u30de\u30eb\u30c1\u30b9\u30ec\u30c3\u30c9\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3067\u4f7f\u7528\u3067\u304d\u307e\u3059\u3002\r\n\r\n## \u30e1\u30e2\u30ea\u7ba1\u7406\r\n\r\n\u30e9\u30a4\u30d6\u30e9\u30ea\u306f\u30b3\u30fc\u30eb\u30d0\u30c3\u30af\u306b\u5f31\u53c2\u7167\u3092\u4f7f\u7528\u3057\u3066\u30e1\u30e2\u30ea\u30ea\u30fc\u30af\u3092\u9632\u304e\u307e\u3059\u3002\u8cfc\u8aad\u3055\u308c\u305f\u30e1\u30bd\u30c3\u30c9\u3092\u6301\u3064\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u304c\u30ac\u30d9\u30fc\u30b8\u30b3\u30ec\u30af\u30b7\u30e7\u30f3\u3055\u308c\u308b\u3068\u3001\u305d\u308c\u3089\u306e\u8cfc\u8aad\u306f\u81ea\u52d5\u7684\u306b\u30af\u30ea\u30fc\u30f3\u30a2\u30c3\u30d7\u3055\u308c\u307e\u3059\u3002\r\n\r\n## \u30d1\u30d5\u30a9\u30fc\u30de\u30f3\u30b9\r\n\r\n- **\u8efd\u91cf**: \u6700\u5c0f\u9650\u306e\u30e1\u30e2\u30ea\u30d5\u30c3\u30c8\u30d7\u30ea\u30f3\u30c8\r\n- **\u9ad8\u901f**: \u9ad8\u983b\u5ea6\u306a\u30a4\u30d9\u30f3\u30c8\u767a\u884c\u306b\u6700\u9069\u5316\r\n- **\u30b9\u30b1\u30fc\u30e9\u30d6\u30eb**: \u6570\u5343\u306e\u30a4\u30d9\u30f3\u30c8\u3068\u8cfc\u8aad\u8005\u3092\u52b9\u7387\u7684\u306b\u51e6\u7406\r\n\r\n## \u30e9\u30a4\u30bb\u30f3\u30b9\r\n\r\nMIT License - \u8a73\u7d30\u306fLICENSE\u30d5\u30a1\u30a4\u30eb\u3092\u3054\u89a7\u304f\u3060\u3055\u3044\u3002\r\n\r\n## \u8ca2\u732e\r\n\r\n\u8ca2\u732e\u3092\u6b53\u8fce\u3057\u307e\u3059\uff01\u30d7\u30eb\u30ea\u30af\u30a8\u30b9\u30c8\u3092\u304a\u6c17\u8efd\u306b\u304a\u9001\u308a\u304f\u3060\u3055\u3044\u3002\r\n\r\n## \u4f5c\u8005\r\n\r\n[tikipiya](https://github.com/tikipiya)\u304c\u4f5c\u6210\r\n",
    "bugtrack_url": null,
    "license": null,
    "summary": "\u4f9d\u5b58\u95a2\u4fc2\u30bc\u30ed\u306e\u8efd\u91cf\u30d1\u30d6\u30ea\u30c3\u30b7\u30e5/\u30b5\u30d6\u30b9\u30af\u30e9\u30a4\u30d6\u30e1\u30c3\u30bb\u30fc\u30b8\u30f3\u30b0\u30e9\u30a4\u30d6\u30e9\u30ea",
    "version": "1.0.0",
    "project_urls": {
        "Bug Reports": "https://github.com/tikipiya/publishsub/issues",
        "Homepage": "https://github.com/tikipiya/publishsub",
        "Source": "https://github.com/tikipiya/publishsub"
    },
    "split_keywords": [
        "pubsub",
        " publish",
        " subscribe",
        " messaging",
        " event",
        " observer",
        " pertern"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "30f18c572258422953bd33d6f748ca20efc508e654b29fc8cd1424c7d1b06f7a",
                "md5": "bf15356be6ed16ed94273b1f95146f84",
                "sha256": "7c40122ed7e1c052d5eadd0f5ef1e36ac27be6713e4611f7daaddd645c0ccafe"
            },
            "downloads": -1,
            "filename": "publishsub-1.0.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "bf15356be6ed16ed94273b1f95146f84",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.7",
            "size": 7627,
            "upload_time": "2025-07-11T12:52:41",
            "upload_time_iso_8601": "2025-07-11T12:52:41.900484Z",
            "url": "https://files.pythonhosted.org/packages/30/f1/8c572258422953bd33d6f748ca20efc508e654b29fc8cd1424c7d1b06f7a/publishsub-1.0.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "3452d08ed36522b7467457ec0ded68dece0539a8a724ac04317c0469b1c58651",
                "md5": "7ee82177068248e1ac8c58d460c70656",
                "sha256": "4fe04c8432512831579466fc9145b65ecbd011568cf08d893bd147c2f49aad6f"
            },
            "downloads": -1,
            "filename": "publishsub-1.0.0.tar.gz",
            "has_sig": false,
            "md5_digest": "7ee82177068248e1ac8c58d460c70656",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.7",
            "size": 19157,
            "upload_time": "2025-07-11T12:52:43",
            "upload_time_iso_8601": "2025-07-11T12:52:43.049122Z",
            "url": "https://files.pythonhosted.org/packages/34/52/d08ed36522b7467457ec0ded68dece0539a8a724ac04317c0469b1c58651/publishsub-1.0.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-07-11 12:52:43",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "tikipiya",
    "github_project": "publishsub",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "requirements": [
        {
            "name": "pytest",
            "specs": [
                [
                    ">=",
                    "6.0"
                ]
            ]
        },
        {
            "name": "pytest-cov",
            "specs": [
                [
                    ">=",
                    "2.0"
                ]
            ]
        },
        {
            "name": "black",
            "specs": [
                [
                    ">=",
                    "22.0"
                ]
            ]
        },
        {
            "name": "flake8",
            "specs": [
                [
                    ">=",
                    "4.0"
                ]
            ]
        }
    ],
    "lcname": "publishsub"
}
        
Elapsed time: 0.42257s