wappa 0.1.9__py3-none-any.whl โ 0.1.10__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of wappa might be problematic. Click here for more details.
- wappa/__init__.py +4 -5
- wappa/api/controllers/webhook_controller.py +5 -2
- wappa/api/dependencies/__init__.py +0 -5
- wappa/api/middleware/error_handler.py +4 -4
- wappa/api/middleware/owner.py +11 -5
- wappa/api/routes/webhooks.py +2 -2
- wappa/cli/__init__.py +1 -1
- wappa/cli/examples/init/app/main.py +2 -1
- wappa/cli/examples/init/app/master_event.py +5 -3
- wappa/cli/examples/json_cache_example/app/__init__.py +1 -1
- wappa/cli/examples/json_cache_example/app/main.py +56 -44
- wappa/cli/examples/json_cache_example/app/master_event.py +181 -145
- wappa/cli/examples/json_cache_example/app/models/__init__.py +1 -1
- wappa/cli/examples/json_cache_example/app/models/json_demo_models.py +32 -51
- wappa/cli/examples/json_cache_example/app/scores/__init__.py +2 -2
- wappa/cli/examples/json_cache_example/app/scores/score_base.py +52 -46
- wappa/cli/examples/json_cache_example/app/scores/score_cache_statistics.py +70 -62
- wappa/cli/examples/json_cache_example/app/scores/score_message_history.py +41 -44
- wappa/cli/examples/json_cache_example/app/scores/score_state_commands.py +83 -71
- wappa/cli/examples/json_cache_example/app/scores/score_user_management.py +73 -57
- wappa/cli/examples/json_cache_example/app/utils/__init__.py +2 -2
- wappa/cli/examples/json_cache_example/app/utils/cache_utils.py +54 -56
- wappa/cli/examples/json_cache_example/app/utils/message_utils.py +85 -80
- wappa/cli/examples/openai_transcript/app/main.py +2 -1
- wappa/cli/examples/openai_transcript/app/master_event.py +31 -22
- wappa/cli/examples/openai_transcript/app/openai_utils/__init__.py +1 -1
- wappa/cli/examples/openai_transcript/app/openai_utils/audio_processing.py +37 -24
- wappa/cli/examples/redis_cache_example/app/__init__.py +1 -1
- wappa/cli/examples/redis_cache_example/app/main.py +56 -44
- wappa/cli/examples/redis_cache_example/app/master_event.py +181 -145
- wappa/cli/examples/redis_cache_example/app/models/redis_demo_models.py +31 -50
- wappa/cli/examples/redis_cache_example/app/scores/__init__.py +2 -2
- wappa/cli/examples/redis_cache_example/app/scores/score_base.py +52 -46
- wappa/cli/examples/redis_cache_example/app/scores/score_cache_statistics.py +70 -62
- wappa/cli/examples/redis_cache_example/app/scores/score_message_history.py +41 -44
- wappa/cli/examples/redis_cache_example/app/scores/score_state_commands.py +83 -71
- wappa/cli/examples/redis_cache_example/app/scores/score_user_management.py +73 -57
- wappa/cli/examples/redis_cache_example/app/utils/__init__.py +2 -2
- wappa/cli/examples/redis_cache_example/app/utils/cache_utils.py +54 -56
- wappa/cli/examples/redis_cache_example/app/utils/message_utils.py +85 -80
- wappa/cli/examples/simple_echo_example/app/__init__.py +1 -1
- wappa/cli/examples/simple_echo_example/app/main.py +41 -33
- wappa/cli/examples/simple_echo_example/app/master_event.py +78 -57
- wappa/cli/examples/wappa_full_example/app/__init__.py +1 -1
- wappa/cli/examples/wappa_full_example/app/handlers/__init__.py +1 -1
- wappa/cli/examples/wappa_full_example/app/handlers/command_handlers.py +134 -126
- wappa/cli/examples/wappa_full_example/app/handlers/message_handlers.py +237 -229
- wappa/cli/examples/wappa_full_example/app/handlers/state_handlers.py +170 -148
- wappa/cli/examples/wappa_full_example/app/main.py +51 -39
- wappa/cli/examples/wappa_full_example/app/master_event.py +179 -120
- wappa/cli/examples/wappa_full_example/app/models/__init__.py +1 -1
- wappa/cli/examples/wappa_full_example/app/models/state_models.py +113 -104
- wappa/cli/examples/wappa_full_example/app/models/user_models.py +92 -76
- wappa/cli/examples/wappa_full_example/app/models/webhook_metadata.py +109 -83
- wappa/cli/examples/wappa_full_example/app/utils/__init__.py +1 -1
- wappa/cli/examples/wappa_full_example/app/utils/cache_utils.py +132 -113
- wappa/cli/examples/wappa_full_example/app/utils/media_handler.py +175 -132
- wappa/cli/examples/wappa_full_example/app/utils/metadata_extractor.py +126 -87
- wappa/cli/main.py +9 -4
- wappa/core/__init__.py +18 -23
- wappa/core/config/settings.py +7 -5
- wappa/core/events/default_handlers.py +1 -1
- wappa/core/factory/wappa_builder.py +38 -25
- wappa/core/plugins/redis_plugin.py +1 -3
- wappa/core/plugins/wappa_core_plugin.py +7 -6
- wappa/core/types.py +12 -12
- wappa/core/wappa_app.py +10 -8
- wappa/database/__init__.py +3 -4
- wappa/domain/enums/messenger_platform.py +1 -2
- wappa/domain/factories/media_factory.py +5 -20
- wappa/domain/factories/message_factory.py +5 -20
- wappa/domain/factories/messenger_factory.py +2 -4
- wappa/domain/interfaces/cache_interface.py +7 -7
- wappa/domain/interfaces/media_interface.py +2 -5
- wappa/domain/models/media_result.py +1 -3
- wappa/domain/models/platforms/platform_config.py +1 -3
- wappa/messaging/__init__.py +9 -12
- wappa/messaging/whatsapp/handlers/whatsapp_media_handler.py +20 -22
- wappa/models/__init__.py +27 -35
- wappa/persistence/__init__.py +12 -15
- wappa/persistence/cache_factory.py +0 -1
- wappa/persistence/json/__init__.py +1 -1
- wappa/persistence/json/cache_adapters.py +37 -25
- wappa/persistence/json/handlers/state_handler.py +60 -52
- wappa/persistence/json/handlers/table_handler.py +51 -49
- wappa/persistence/json/handlers/user_handler.py +71 -55
- wappa/persistence/json/handlers/utils/file_manager.py +42 -39
- wappa/persistence/json/handlers/utils/key_factory.py +1 -1
- wappa/persistence/json/handlers/utils/serialization.py +13 -11
- wappa/persistence/json/json_cache_factory.py +4 -8
- wappa/persistence/json/storage_manager.py +66 -79
- wappa/persistence/memory/__init__.py +1 -1
- wappa/persistence/memory/cache_adapters.py +37 -25
- wappa/persistence/memory/handlers/state_handler.py +62 -52
- wappa/persistence/memory/handlers/table_handler.py +59 -53
- wappa/persistence/memory/handlers/user_handler.py +75 -55
- wappa/persistence/memory/handlers/utils/key_factory.py +1 -1
- wappa/persistence/memory/handlers/utils/memory_store.py +75 -71
- wappa/persistence/memory/handlers/utils/ttl_manager.py +59 -67
- wappa/persistence/memory/memory_cache_factory.py +3 -7
- wappa/persistence/memory/storage_manager.py +52 -62
- wappa/persistence/redis/cache_adapters.py +27 -21
- wappa/persistence/redis/ops.py +11 -11
- wappa/persistence/redis/redis_client.py +4 -6
- wappa/persistence/redis/redis_manager.py +12 -4
- wappa/processors/factory.py +5 -5
- wappa/schemas/factory.py +2 -5
- wappa/schemas/whatsapp/message_types/errors.py +3 -12
- wappa/schemas/whatsapp/validators.py +3 -3
- wappa/webhooks/__init__.py +17 -18
- wappa/webhooks/factory.py +3 -5
- wappa/webhooks/whatsapp/__init__.py +10 -13
- wappa/webhooks/whatsapp/message_types/audio.py +0 -4
- wappa/webhooks/whatsapp/message_types/document.py +1 -9
- wappa/webhooks/whatsapp/message_types/errors.py +3 -12
- wappa/webhooks/whatsapp/message_types/location.py +1 -21
- wappa/webhooks/whatsapp/message_types/sticker.py +1 -5
- wappa/webhooks/whatsapp/message_types/text.py +0 -6
- wappa/webhooks/whatsapp/message_types/video.py +1 -20
- wappa/webhooks/whatsapp/status_models.py +2 -2
- wappa/webhooks/whatsapp/validators.py +3 -3
- {wappa-0.1.9.dist-info โ wappa-0.1.10.dist-info}/METADATA +362 -8
- {wappa-0.1.9.dist-info โ wappa-0.1.10.dist-info}/RECORD +126 -126
- {wappa-0.1.9.dist-info โ wappa-0.1.10.dist-info}/WHEEL +0 -0
- {wappa-0.1.9.dist-info โ wappa-0.1.10.dist-info}/entry_points.txt +0 -0
- {wappa-0.1.9.dist-info โ wappa-0.1.10.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
# Removed direct config import
|
|
2
2
|
# from config.env import OPENAI_API_KEY
|
|
3
|
-
from wappa.core.logging import get_logger # Corrected relative import
|
|
4
|
-
from pathlib import Path
|
|
5
|
-
from typing import Union, BinaryIO
|
|
6
3
|
import io
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from typing import BinaryIO
|
|
7
6
|
|
|
8
7
|
from openai import AsyncOpenAI
|
|
9
8
|
|
|
9
|
+
from wappa.core.logging import get_logger # Corrected relative import
|
|
10
|
+
|
|
10
11
|
# Initialize logger with class name
|
|
11
12
|
logger = get_logger("AudioProcessingService")
|
|
12
13
|
|
|
@@ -16,7 +17,9 @@ class AudioProcessingService:
|
|
|
16
17
|
# Accept api_key in init
|
|
17
18
|
self.async_openai_client = async_openai_client
|
|
18
19
|
|
|
19
|
-
async def transcribe_audio(
|
|
20
|
+
async def transcribe_audio(
|
|
21
|
+
self, audio_source: str | Path | bytes | BinaryIO, filename: str = "audio"
|
|
22
|
+
) -> str:
|
|
20
23
|
"""
|
|
21
24
|
Transcribes the audio using OpenAI's speech-to-text API with the gpt-4o-mini-transcribe model.
|
|
22
25
|
|
|
@@ -32,42 +35,52 @@ class AudioProcessingService:
|
|
|
32
35
|
"""
|
|
33
36
|
try:
|
|
34
37
|
# Handle different input types
|
|
35
|
-
if isinstance(audio_source,
|
|
38
|
+
if isinstance(audio_source, str | Path):
|
|
36
39
|
# File path input (original behavior)
|
|
37
40
|
audio_path = Path(audio_source)
|
|
38
41
|
with audio_path.open("rb") as audio_file:
|
|
39
|
-
transcription =
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
42
|
+
transcription = (
|
|
43
|
+
await self.async_openai_client.audio.transcriptions.create(
|
|
44
|
+
model="gpt-4o-mini-transcribe",
|
|
45
|
+
file=audio_file,
|
|
46
|
+
response_format="json",
|
|
47
|
+
)
|
|
43
48
|
)
|
|
44
49
|
logger.debug(f"Transcription successful for file: {audio_path}")
|
|
45
|
-
|
|
50
|
+
|
|
46
51
|
elif isinstance(audio_source, bytes):
|
|
47
52
|
# Bytes input - create BytesIO stream
|
|
48
53
|
audio_stream = io.BytesIO(audio_source)
|
|
49
54
|
audio_stream.name = filename # OpenAI API needs a filename attribute
|
|
50
|
-
transcription =
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
55
|
+
transcription = (
|
|
56
|
+
await self.async_openai_client.audio.transcriptions.create(
|
|
57
|
+
model="gpt-4o-mini-transcribe",
|
|
58
|
+
file=audio_stream,
|
|
59
|
+
response_format="json",
|
|
60
|
+
)
|
|
61
|
+
)
|
|
62
|
+
logger.debug(
|
|
63
|
+
f"Transcription successful for bytes data ({len(audio_source)} bytes)"
|
|
54
64
|
)
|
|
55
|
-
|
|
56
|
-
|
|
65
|
+
|
|
57
66
|
else:
|
|
58
67
|
# File-like object input
|
|
59
68
|
# Ensure it has a name attribute for OpenAI API
|
|
60
|
-
if not hasattr(audio_source,
|
|
69
|
+
if not hasattr(audio_source, "name"):
|
|
61
70
|
audio_source.name = filename
|
|
62
|
-
transcription =
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
71
|
+
transcription = (
|
|
72
|
+
await self.async_openai_client.audio.transcriptions.create(
|
|
73
|
+
model="gpt-4o-mini-transcribe",
|
|
74
|
+
file=audio_source,
|
|
75
|
+
response_format="json",
|
|
76
|
+
)
|
|
77
|
+
)
|
|
78
|
+
logger.debug(
|
|
79
|
+
f"Transcription successful for file-like object: {getattr(audio_source, 'name', 'unknown')}"
|
|
66
80
|
)
|
|
67
|
-
|
|
68
|
-
|
|
81
|
+
|
|
69
82
|
return transcription.text
|
|
70
|
-
|
|
83
|
+
|
|
71
84
|
except FileNotFoundError:
|
|
72
85
|
logger.error(f"Audio file not found for transcription: {audio_source}")
|
|
73
86
|
raise
|
|
@@ -44,31 +44,31 @@ from .master_event import RedisCacheExampleHandler
|
|
|
44
44
|
def validate_configuration() -> bool:
|
|
45
45
|
"""
|
|
46
46
|
Validate required configuration settings.
|
|
47
|
-
|
|
47
|
+
|
|
48
48
|
Returns:
|
|
49
49
|
True if configuration is valid, False otherwise
|
|
50
50
|
"""
|
|
51
|
-
|
|
51
|
+
|
|
52
52
|
# Check required WhatsApp credentials
|
|
53
53
|
missing_configs = []
|
|
54
|
-
|
|
54
|
+
|
|
55
55
|
if not settings.wp_access_token:
|
|
56
56
|
missing_configs.append("WP_ACCESS_TOKEN")
|
|
57
|
-
|
|
57
|
+
|
|
58
58
|
if not settings.wp_phone_id:
|
|
59
59
|
missing_configs.append("WP_PHONE_ID")
|
|
60
|
-
|
|
60
|
+
|
|
61
61
|
if not settings.wp_bid:
|
|
62
62
|
missing_configs.append("WP_BID")
|
|
63
|
-
|
|
63
|
+
|
|
64
64
|
if not settings.has_redis:
|
|
65
65
|
missing_configs.append("REDIS_URL")
|
|
66
|
-
|
|
66
|
+
|
|
67
67
|
if missing_configs:
|
|
68
68
|
logger.error(f"โ Missing required configuration: {', '.join(missing_configs)}")
|
|
69
69
|
logger.error("๐ก Create a .env file with the required credentials")
|
|
70
70
|
return False
|
|
71
|
-
|
|
71
|
+
|
|
72
72
|
logger.info("โ
Configuration validation passed")
|
|
73
73
|
return True
|
|
74
74
|
|
|
@@ -76,14 +76,14 @@ def validate_configuration() -> bool:
|
|
|
76
76
|
def display_startup_information() -> None:
|
|
77
77
|
"""
|
|
78
78
|
Display startup information and demo features.
|
|
79
|
-
|
|
79
|
+
|
|
80
80
|
Shows configuration status, architecture overview,
|
|
81
81
|
and available demo features.
|
|
82
82
|
"""
|
|
83
83
|
print(f"๐ Wappa v{__version__} - Redis Cache Example (SOLID Architecture)")
|
|
84
84
|
print("=" * 80)
|
|
85
85
|
print()
|
|
86
|
-
|
|
86
|
+
|
|
87
87
|
print("๐๏ธ *SOLID ARCHITECTURE IMPLEMENTATION:*")
|
|
88
88
|
print(" โข Single Responsibility: Each score module has one specific concern")
|
|
89
89
|
print(" โข Open/Closed: New score modules can be added without modification")
|
|
@@ -91,22 +91,28 @@ def display_startup_information() -> None:
|
|
|
91
91
|
print(" โข Interface Segregation: Clean, focused interfaces for each concern")
|
|
92
92
|
print(" โข Dependency Inversion: Dependencies injected through abstractions")
|
|
93
93
|
print()
|
|
94
|
-
|
|
94
|
+
|
|
95
95
|
print("๐ *CONFIGURATION STATUS:*")
|
|
96
|
-
print(
|
|
97
|
-
|
|
96
|
+
print(
|
|
97
|
+
f" โข Access Token: {'โ
Configured' if settings.wp_access_token else 'โ Missing'}"
|
|
98
|
+
)
|
|
99
|
+
print(
|
|
100
|
+
f" โข Phone ID: {settings.wp_phone_id if settings.wp_phone_id else 'โ Missing'}"
|
|
101
|
+
)
|
|
98
102
|
print(f" โข Business ID: {'โ
Configured' if settings.wp_bid else 'โ Missing'}")
|
|
99
103
|
print(f" โข Redis URL: {'โ
Configured' if settings.has_redis else 'โ Missing'}")
|
|
100
|
-
print(
|
|
104
|
+
print(
|
|
105
|
+
f" โข Environment: {'๐ ๏ธ Development' if settings.is_development else '๐ Production'}"
|
|
106
|
+
)
|
|
101
107
|
print()
|
|
102
|
-
|
|
108
|
+
|
|
103
109
|
print("๐ฏ *SCORE MODULES (BUSINESS LOGIC):*")
|
|
104
110
|
print(" โข UserManagementScore: User profile and caching logic")
|
|
105
111
|
print(" โข MessageHistoryScore: Message logging and /HISTORY command")
|
|
106
|
-
print(" โข StateCommandsScore: /WAPPA and /EXIT command processing")
|
|
112
|
+
print(" โข StateCommandsScore: /WAPPA and /EXIT command processing")
|
|
107
113
|
print(" โข CacheStatisticsScore: Cache monitoring and /STATS command")
|
|
108
114
|
print()
|
|
109
|
-
|
|
115
|
+
|
|
110
116
|
print("๐งช *DEMO FEATURES:*")
|
|
111
117
|
print(" 1. Send any message โ User profile created/updated + message logged")
|
|
112
118
|
print(" 2. Send '/WAPPA' โ Enter special state with cache management")
|
|
@@ -115,14 +121,14 @@ def display_startup_information() -> None:
|
|
|
115
121
|
print(" 5. Send '/HISTORY' โ View your last 20 messages with timestamps")
|
|
116
122
|
print(" 6. Send '/STATS' โ View comprehensive cache statistics")
|
|
117
123
|
print()
|
|
118
|
-
|
|
124
|
+
|
|
119
125
|
print("๐ *REDIS CACHE ARCHITECTURE:*")
|
|
120
126
|
print(" โข user_cache: User profiles with dependency injection")
|
|
121
|
-
print(" โข table_cache: Message history with BaseModel auto-serialization")
|
|
127
|
+
print(" โข table_cache: Message history with BaseModel auto-serialization")
|
|
122
128
|
print(" โข state_cache: Command state management with TTL")
|
|
123
129
|
print(" โข Comprehensive error handling and logging")
|
|
124
130
|
print()
|
|
125
|
-
|
|
131
|
+
|
|
126
132
|
print("๐ง *TECHNICAL FEATURES:*")
|
|
127
133
|
print(" โข Dependency injection with interface abstractions")
|
|
128
134
|
print(" โข Score module registry with automatic discovery")
|
|
@@ -136,22 +142,22 @@ def display_startup_information() -> None:
|
|
|
136
142
|
def create_wappa_application() -> Wappa:
|
|
137
143
|
"""
|
|
138
144
|
Create and configure the Wappa application.
|
|
139
|
-
|
|
145
|
+
|
|
140
146
|
This function follows Single Responsibility Principle by focusing
|
|
141
147
|
only on application creation and initial configuration.
|
|
142
|
-
|
|
148
|
+
|
|
143
149
|
Returns:
|
|
144
150
|
Configured Wappa application instance
|
|
145
151
|
"""
|
|
146
|
-
|
|
152
|
+
|
|
147
153
|
try:
|
|
148
154
|
# Create Wappa instance with Redis cache
|
|
149
155
|
logger.info("๐๏ธ Creating Wappa application with Redis cache...")
|
|
150
156
|
app = Wappa(cache="redis")
|
|
151
|
-
|
|
157
|
+
|
|
152
158
|
logger.info("โ
Wappa application created successfully")
|
|
153
159
|
return app
|
|
154
|
-
|
|
160
|
+
|
|
155
161
|
except Exception as e:
|
|
156
162
|
logger.error(f"โ Failed to create Wappa application: {e}")
|
|
157
163
|
raise
|
|
@@ -160,50 +166,54 @@ def create_wappa_application() -> Wappa:
|
|
|
160
166
|
def main() -> None:
|
|
161
167
|
"""
|
|
162
168
|
Main application entry point.
|
|
163
|
-
|
|
169
|
+
|
|
164
170
|
Demonstrates SOLID principles in action:
|
|
165
171
|
- Single Responsibility: Each function has one clear purpose
|
|
166
172
|
- Dependency Inversion: Dependencies flow from abstractions
|
|
167
173
|
- Open/Closed: System is open for extension via score modules
|
|
168
174
|
"""
|
|
169
|
-
|
|
175
|
+
|
|
170
176
|
logger.info("๐ Starting Redis Cache Example with SOLID Architecture")
|
|
171
|
-
|
|
177
|
+
|
|
172
178
|
try:
|
|
173
179
|
# Display startup information
|
|
174
180
|
display_startup_information()
|
|
175
|
-
|
|
181
|
+
|
|
176
182
|
# Validate configuration before proceeding
|
|
177
183
|
if not validate_configuration():
|
|
178
|
-
logger.error(
|
|
184
|
+
logger.error(
|
|
185
|
+
"โ Configuration validation failed - cannot start application"
|
|
186
|
+
)
|
|
179
187
|
return
|
|
180
|
-
|
|
188
|
+
|
|
181
189
|
# Create Wappa application
|
|
182
190
|
app = create_wappa_application()
|
|
183
|
-
|
|
191
|
+
|
|
184
192
|
# Create and set the SOLID WappaEventHandler implementation
|
|
185
193
|
handler = RedisCacheExampleHandler()
|
|
186
194
|
app.set_event_handler(handler)
|
|
187
|
-
|
|
188
|
-
logger.info(
|
|
189
|
-
|
|
195
|
+
|
|
196
|
+
logger.info(
|
|
197
|
+
"โ
Application initialization completed with SOLID WappaEventHandler"
|
|
198
|
+
)
|
|
199
|
+
|
|
190
200
|
print("๐ Starting SOLID Redis cache demo server...")
|
|
191
201
|
print("๐ก Press CTRL+C to stop the server")
|
|
192
202
|
print("=" * 80)
|
|
193
203
|
print()
|
|
194
|
-
|
|
204
|
+
|
|
195
205
|
# Start the application
|
|
196
206
|
# The framework will handle dependency injection automatically
|
|
197
207
|
app.run()
|
|
198
|
-
|
|
208
|
+
|
|
199
209
|
except KeyboardInterrupt:
|
|
200
210
|
logger.info("๐ Application stopped by user")
|
|
201
211
|
print("\n๐ Redis cache demo stopped by user")
|
|
202
|
-
|
|
212
|
+
|
|
203
213
|
except Exception as e:
|
|
204
214
|
logger.error(f"โ Application startup error: {e}", exc_info=True)
|
|
205
215
|
print(f"\nโ Server error: {e}")
|
|
206
|
-
|
|
216
|
+
|
|
207
217
|
finally:
|
|
208
218
|
logger.info("๐ Redis cache demo completed")
|
|
209
219
|
print("๐ Redis cache demo completed")
|
|
@@ -218,17 +228,19 @@ def main() -> None:
|
|
|
218
228
|
try:
|
|
219
229
|
logger.info("๐ฆ Creating module-level Wappa application instance")
|
|
220
230
|
app = Wappa(cache="redis")
|
|
221
|
-
|
|
231
|
+
|
|
222
232
|
# Create and set the SOLID WappaEventHandler implementation
|
|
223
233
|
handler = RedisCacheExampleHandler()
|
|
224
234
|
app.set_event_handler(handler)
|
|
225
|
-
|
|
226
|
-
logger.info(
|
|
227
|
-
|
|
235
|
+
|
|
236
|
+
logger.info(
|
|
237
|
+
"โ
Module-level application instance ready with SOLID WappaEventHandler"
|
|
238
|
+
)
|
|
239
|
+
|
|
228
240
|
except Exception as e:
|
|
229
241
|
logger.error(f"โ Failed to create module-level app instance: {e}")
|
|
230
242
|
raise
|
|
231
243
|
|
|
232
244
|
|
|
233
245
|
if __name__ == "__main__":
|
|
234
|
-
main()
|
|
246
|
+
main()
|